Add support for big numbers

dev
Alberto Restifo 2020-04-24 11:57:12 +02:00
parent 4929f2487b
commit 5be5e3b20e
3 changed files with 27 additions and 4 deletions

View File

@ -27,9 +27,9 @@ tests = [
{ %(1000000), "1a 00 0f 42 40" },
{ %(1000000000000), "1b 00 00 00 e8 d4 a5 10 00" },
{ %(18446744073709551615), "1b ff ff ff ff ff ff ff ff" },
# { %(18446744073709551616), "c2 49 01 00 00 00 00 00 00 00 00" },
{ %(18446744073709551616), "c2 49 01 00 00 00 00 00 00 00 00" },
{ %(-18446744073709551616), "3b ff ff ff ff ff ff ff ff" },
# { %(-18446744073709551617), "c3 49 01 00 00 00 00 00 00 00 00" },
{ %(-18446744073709551617), "c3 49 01 00 00 00 00 00 00 00 00" },
{ %(-1), "20" },
{ %(-10), "29" },
{ %(-100), "38 63" },
@ -54,7 +54,7 @@ tests = [
{ %(simple(255)), "f8 ff" },
{ %(0("2013-03-21T20:04:00Z")), "c0 74 32 30 31 33 2d 30 33 2d 32 31 54 32 30 3a 30 34 3a 30 30 5a" },
{ %(1(1363896240)), "c1 1a 51 4b 67 b0" },
# { %(1(1363896240.5)), "c1 fb 41 d4 52 d9 ec 20 00 00" },
{ %(1(1363896240.5)), "c1 fb 41 d4 52 d9 ec 20 00 00" },
{ %(23(h'01020304')), "d7 44 01 02 03 04" },
{ %(24(h'6449455446')), "d8 18 45 64 49 45 54 46" },
{ %(32("http://www.example.com")), "d8 20 76 68 74 74 70 3a 2f 2f 77 77 77 2e 65 78 61 6d 70 6c 65 2e 63 6f 6d" },

View File

@ -1,3 +1,5 @@
require "big"
require "./cbor/**"
# TODO: Write documentation for `CBOR`

View File

@ -53,7 +53,14 @@ class CBOR::Diagnostic
when Token::SimpleValueT
token.value.to_diagnostic
when Token::TagT
"#{token.value.value.to_s}(#{next_value})"
case token.value
when Tag::PositiveBigNum
read_big_int
when Tag::NegativeBigNum
read_big_int(negative: true)
else
"#{token.value.value.to_s}(#{next_value})"
end
when Token::FloatT
return "NaN" if token.value.nan?
return token.value.to_s if token.value.finite?
@ -103,6 +110,20 @@ class CBOR::Diagnostic
key_pairs
end
private def read_big_int(negative : Bool = false) : String
token = @lexer.next_token
raise ParseError.new("Unexpected EOF after tag") unless token
raise ParseError.new("Unexpected type #{token.class}, want Token::BytesT") unless token.is_a?(Token::BytesT)
big = BigInt.new(token.value.hexstring, 16)
if negative
big *= -1
big -= 1
end
big.to_s
end
private def key_value(key : Token::T, value : Token::T) : String
"#{to_diagnostic(key)}: #{to_diagnostic(value)}"
end