diff --git a/spec/cbor/from_cbor_spec.cr b/spec/cbor/from_cbor_spec.cr index 3f7a623..ba31c6b 100644 --- a/spec/cbor/from_cbor_spec.cr +++ b/spec/cbor/from_cbor_spec.cr @@ -39,6 +39,7 @@ describe "CBOR helpers on basic types" do {TestEnum, Bytes[0x1a, 0x00, 0x00, 0x00, 0x01], TestEnum::Foo}, {Tuple(Int8, Int8), Bytes[0x82, 0x01, 0x02], {1_i8, 2_i8}}, {NamedTuple(a: UInt8, b: Array(UInt8)), Bytes[0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03], {a: 1_u8, b: [2_u8, 3_u8]}}, + {BigInt, Bytes[0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], BigInt.new("18446744073709551616")}, ] tests.each do |tt| diff --git a/src/cbor/from_cbor.cr b/src/cbor/from_cbor.cr index 4a0cc47..8b0a53a 100644 --- a/src/cbor/from_cbor.cr +++ b/src/cbor/from_cbor.cr @@ -19,6 +19,10 @@ end {% end %} +def Int128.new(decoder : CBOR::Decoder) + decoder.read_int.to_i128 +end + {% for size in [32, 64] %} def Float{{size.id}}.new(decoder : CBOR::Decoder) @@ -141,7 +145,26 @@ def Time.new(decoder : CBOR::Decoder) Time.unix_ms((BigFloat.new(num) * 1_000).to_u64) end else - raise CBOR::ParseError.new("Expected tag to have value 0 or 1, got #{tag.value.to_s}") + raise CBOR::ParseError.new("Expected tag to have value 0 or 1, got #{tag.value}") + end +end + +# Reads the CBOR value as a BigInt. The value must be surrounded by a tag with +# value 2 (positive) or 3 (negative). +def BigInt.new(decoder : CBOR::Decoder) + case tag = decoder.read_tag + when CBOR::Tag::PositiveBigNum, + CBOR::Tag::NegativeBigNum + big = new(decoder.read_bytes.hexstring, 16) + + if tag == CBOR::Tag::NegativeBigNum + big *= -1 + big -= 1 + end + + big + else + raise CBOR::ParseError.new("Expected tag to have value 2 or 3, got #{tag.value}") end end