Skip to content

feat(cbor): Add BigInteger support with RFC 8949 §3.4.3 compliance#4611

Open
e-thoman wants to merge 7 commits intosmithy-lang:mainfrom
e-thoman:feature/cbor-big-integer
Open

feat(cbor): Add BigInteger support with RFC 8949 §3.4.3 compliance#4611
e-thoman wants to merge 7 commits intosmithy-lang:mainfrom
e-thoman:feature/cbor-big-integer

Conversation

@e-thoman
Copy link
Copy Markdown

Add CBOR encoding and decoding support for BigInteger using CBOR tags 2 (positive bignum) and 3 (negative bignum) as specified by RFC 8949 §3.4.3 and the Smithy RPC v2 CBOR protocol.

  • Preferred serialization: values fitting in u64/i64 use major types 0/1 instead of bignum tags
  • Tag 3 correctly encodes -1-n per RFC 8949
  • Handle minicbor Int type for major type 1 values exceeding i64 range
  • Add num-bigint dependency to aws-smithy-cbor
  • Codegen: BigIntegerShape delegates to decoder.big_integer() / encoder.big_integer()
  • BigDecimal remains unsupported with CBOR (fails at codegen time)
  • Comprehensive tests: round-trip, RFC 8949 Appendix A interop, edge cases

Resolves: smithy-rs#4473

Motivation and Context

BigInteger was previously unsupported with the CBOR protocol — attempting to use a BigIntegerShape in a Smithy model with RPC v2 CBOR would fail at codegen time with a CodegenException.
This blocked any service or client that needed arbitrary-precision integers over CBOR. The Smithy RPC v2 CBOR spec requires BigInteger support via CBOR tags 2 and 3 (RFC 8949 §3.4.3), and this
change implements that requirement. See smithy-rs#4473.

Description

Rust runtime (aws-smithy-cbor):

  • Added big_integer() to Encoder — writes values using preferred serialization (major type 0/1 for values fitting u64/i64, tags 2/3 for larger values). Tag 3 encodes the byte string as n
    where the value is -1 - n per RFC 8949.
  • Added big_integer() to Decoder — reads CBOR tags 2/3 (bignum), plain unsigned/signed integers (major types 0/1), and minicbor Int type for major type 1 values exceeding i64 range.
  • Added num-bigint 0.4 dependency for arbitrary-precision integer arithmetic.
  • Added strip_leading_zeroes() helper for preferred bignum serialization.

Codegen (codegen-core):

  • CborParserGenerator.kt: BigIntegerShape now emits decoder.big_integer() instead of throwing CodegenException.
  • CborSerializerGenerator.kt: BigIntegerShape now emits encoder.big_integer() instead of throwing CodegenException.
  • BigDecimalShape remains unsupported (still throws CodegenException).

Testing

  • 18 new Rust unit tests in aws-smithy-cbor covering:
    • Round-trip encode/decode for positive, negative, and large values
    • RFC 8949 Appendix A interoperability vectors (2^64, -2^64-1)
    • Preferred serialization verification (small values use major types 0/1, not tags)
    • Edge cases: empty byte strings for tags 2/3, invalid tag rejection, major type 1 values exceeding i64
    • Leading zero stripping in bignum byte strings
  • Updated Kotlin codegen tests to verify successful code generation instead of expecting CodegenException
  • All 29 aws-smithy-cbor tests pass

Checklist

  • For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "client," "server," or both in the
    applies_to key.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Add CBOR encoding and decoding support for BigInteger using CBOR tags 2
(positive bignum) and 3 (negative bignum) as specified by RFC 8949
§3.4.3 and the Smithy RPC v2 CBOR protocol.

- Preferred serialization: values fitting in u64/i64 use major types
  0/1 instead of bignum tags
- Tag 3 correctly encodes -1-n per RFC 8949
- Handle minicbor Int type for major type 1 values exceeding i64 range
- Add num-bigint dependency to aws-smithy-cbor
- Codegen: BigIntegerShape delegates to decoder.big_integer() /
  encoder.big_integer()
- BigDecimal remains unsupported with CBOR (fails at codegen time)
- Comprehensive tests: round-trip, RFC 8949 Appendix A interop, edge
  cases

Resolves: smithy-rs#4473
@e-thoman e-thoman requested review from a team as code owners April 21, 2026 15:50
@@ -125,6 +125,65 @@ impl Encoder {
}

/// Writes a blob. Collapses header+data into a single reserve+write.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this comment was accidentally detached from pub fn blob below


#[test]
fn big_integer_round_trip_positive() {
for value in ["0", "1", "23", "256", "65535", "18446744073709551615"] {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also test round-tripping of positive signed values here? (e.g. +123)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants