--- CBOR-XS/XS.pm 2016/04/25 21:57:57 1.57 +++ CBOR-XS/XS.pm 2016/04/26 16:07:04 1.58 @@ -940,6 +940,15 @@ See L for more info. +=item 30 (rational numbers) + +These tags are decoded into L objects. The corresponding +C method encodes rational numbers with denominator +C<1> via their numerator only, i.e., they become normal integers or +C. + +See L for more info. + =item 21, 22, 23 (expected later JSON conversion) CBOR::XS is not a CBOR-to-JSON converter, and will simply ignore these @@ -1010,25 +1019,31 @@ CBOR::XS provides a C method for both L and L that tries to encode the number in the simplest possible way, that is, either a CBOR integer, a CBOR bigint/decimal fraction (tag -4) or an arbitrary-exponent decimal fraction (tag 264). +4) or an arbitrary-exponent decimal fraction (tag 264). Rational numbers +(L, tag 30) can also contain bignums as members. -It will also understand base-2 bigfloat or arbitrary-exponent bigfloats -(tags 5 and 265), but it will never generate these on its own. +CBOR::XS will also understand base-2 bigfloat or arbitrary-exponent +bigfloats (tags 5 and 265), but it will never generate these on its own. Using the built-in L support, encoding and decoding decimal fractions is generally fast. Decoding bigints can be slow for very -big numbers, and decoding bigfloats or arbitrary-exponent bigfloats can be -extremely slow (minutes, decades) for large exponents. +big numbers (tens of thousands of digits, something that could potentially +be caught by limiting the size of CBOR texts), and decoding bigfloats or +arbitrary-exponent bigfloats can be I slow (minutes, decades) +for large exponents (roughly 40 bit and longer). Additionally, L can take advantage of other bignum -libraries, such as L, which cannot handle big -floats with large exponents, and might simply abort or crash your program, -due to their code quality. +libraries, such as L, which cannot handle big floats with large +exponents, and might simply abort or crash your program, due to their code +quality. This can be a concern if you want to parse untrusted CBOR. If it is, you -need to disable decoding of tag 2 (bigint) and 3 (negative bigint) types, -which will also disable bigfloat support (to be sure, you can also disable -types 4, 5, 264 and 265). +might want to disable decoding of tag 2 (bigint) and 3 (negative bigint) +types. You should also disable types 5 and 265, as these can be slow even +without bigints. + +Disabling bigints will also partially or fully disable types that rely on +them, e.g. rational numbers that use bignums. =head1 CBOR IMPLEMENTATION NOTES @@ -1125,11 +1140,26 @@ Math::BigFloat->new ($_[1][1] . "E" . $_[1][0]) }, + 264 => sub { # decimal fraction with arbitrary exponent + require Math::BigFloat; + Math::BigFloat->new ($_[1][1] . "E" . $_[1][0]) + }, + 5 => sub { # bigfloat, array require Math::BigFloat; scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0]) }, + 265 => sub { # bigfloat with arbitrary exponent + require Math::BigFloat; + scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0]) + }, + + 30 => sub { # rational number + require Math::BigRat; + Math::BigRat->new ("$_[1][0]/$_[1][1]") # separate parameters only work in recent versons + }, + 21 => sub { pop }, # expected conversion to base64url encoding 22 => sub { pop }, # expected conversion to base64 encoding 23 => sub { pop }, # expected conversion to base16 encoding @@ -1145,16 +1175,6 @@ # 34 # base64 rfc46484, utf-8 # 35 # regex pcre/ecma262, utf-8 # 36 # mime message rfc2045, utf-8 - - 264 => sub { # decimal fraction with arbitrary exponent - require Math::BigFloat; - Math::BigFloat->new ($_[1][1] . "E" . $_[1][0]) - }, - - 265 => sub { # bigfloat with arbitrary exponent - require Math::BigFloat; - scalar Math::BigFloat->new ($_[1][1]) * Math::BigFloat->new (2)->bpow ($_[1][0]) - }, ); sub CBOR::XS::default_filter { @@ -1185,6 +1205,14 @@ : tag 264, [$e, $m] } +sub Math::BigRat::TO_CBOR { + my ($n, $d) = $_[0]->parts; + + $d == 1 + ? $n + : tag 30, [$n, $d] +} + sub Time::Piece::TO_CBOR { tag 1, 0 + $_[0]->epoch }