Implement floats

dev
Alberto Restifo 2020-04-24 00:05:50 +02:00
parent e7f4426062
commit a78d06f33a
5 changed files with 43 additions and 20 deletions

View File

@ -9,9 +9,16 @@ in Crystal.
- Full RFC7049 support - Full RFC7049 support
- Full support for diagnostic notation - Full support for diagnostic notation
- Assign a field to a type base on the CBOR tag
- Support for a wide range of IANA CBOR Tags
## Limitations ## Limitations
### Half-precision floating point is not supported
Crystal doesn't have a `Float16` type, so half-precision floating point numbers
are not supported for the time being.
### Maximum Array/String array/Bytes array length ### Maximum Array/String array/Bytes array length
The spec allows for the maximum length of arrays, string arrays and bytes array The spec allows for the maximum length of arrays, string arrays and bytes array

View File

@ -1,14 +1,6 @@
require "./spec_helper" require "./spec_helper"
# All those tests have been exported from the RFC7049 appendix A. # All those tests have been exported from the RFC7049 appendix A.
#
# Some test results have been modified as the tool doesn't support
# the full diagnostic notation as per RFC.
#
# Specifically:
#
# * Removed the undescore marking the start of infinite stirngs, bytes and
# array. This implementation doesn't expose the difference between the two.
tests = [ tests = [
{ %(0), "00" }, { %(0), "00" },
@ -32,25 +24,25 @@ tests = [
# { %(0.0), "f9 00 00" }, # { %(0.0), "f9 00 00" },
# { %(-0.0), "f9 80 00" }, # { %(-0.0), "f9 80 00" },
# { %(1.0), "f9 3c 00" }, # { %(1.0), "f9 3c 00" },
# { %(1.1), "fb 3f f1 99 99 99 99 99 9a" }, { %(1.1), "fb 3f f1 99 99 99 99 99 9a" },
# { %(1.5), "f9 3e 00" }, # { %(1.5), "f9 3e 00" },
# { %(65504.0), "f9 7b ff" }, # { %(65504.0), "f9 7b ff" },
# { %(100000.0), "fa 47 c3 50 00" }, { %(100000.0), "fa 47 c3 50 00" },
# { %(3.4028234663852886e+38), "fa 7f 7f ff ff" }, # { %(3.4028234663852886e+38), "fa 7f 7f ff ff" }, TODO: Not precise enough?
# { %(1.0e+300), "fb 7e 37 e4 3c 88 00 75 9c" }, { %(1.0e+300), "fb 7e 37 e4 3c 88 00 75 9c" },
# { %(5.960464477539063e-8), "f9 00 01" }, # { %(5.960464477539063e-8), "f9 00 01" },
# { %(0.00006103515625), "f9 04 00" }, # { %(0.00006103515625), "f9 04 00" },
# { %(-4.0), "f9 c4 00" }, # { %(-4.0), "f9 c4 00" },
# { %(-4.1), "fb c0 10 66 66 66 66 66 66" }, { %(-4.1), "fb c0 10 66 66 66 66 66 66" },
# { %(Infinity), "f9 7c 00" }, # { %(Infinity), "f9 7c 00" },
# { %(NaN), "f9 7e 00" }, # { %(NaN), "f9 7e 00" },
# { %(-Infinity), "f9 fc 00" }, # { %(-Infinity), "f9 fc 00" },
# { %(Infinity), "fa 7f 80 00 00" }, { %(Infinity), "fa 7f 80 00 00" },
# { %(NaN), "fa 7f c0 00 00" }, { %(NaN), "fa 7f c0 00 00" },
# { %(-Infinity), "fa ff 80 00 00" }, { %(-Infinity), "fa ff 80 00 00" },
# { %(Infinity), "fb 7f f0 00 00 00 00 00 00" }, { %(Infinity), "fb 7f f0 00 00 00 00 00 00" },
# { %(NaN), "fb 7f f8 00 00 00 00 00 00" }, { %(NaN), "fb 7f f8 00 00 00 00 00 00" },
# { %(-Infinity), "fb ff f0 00 00 00 00 00 00" }, { %(-Infinity), "fb ff f0 00 00 00 00 00 00" },
{ %(false), "f4" }, { %(false), "f4" },
{ %(true), "f5" }, { %(true), "f5" },
{ %(null), "f6" }, { %(null), "f6" },

View File

@ -54,6 +54,20 @@ class CBOR::Diagnostic
token.value.to_diagnostic token.value.to_diagnostic
when Token::TagT when Token::TagT
"#{token.value.value.to_s}(#{next_value})" "#{token.value.value.to_s}(#{next_value})"
when Token::FloatT
return "NaN" if token.value.nan?
return token.value.to_s if token.value.finite?
case value = token.value
when Float32
return "Infinity" if value == Float32::INFINITY
"-Infinity"
when Float64
return "Infinity" if value == Float64::INFINITY
"-Infinity"
else
token.value.to_s
end
else else
token.inspect token.inspect
end end

View File

@ -81,9 +81,14 @@ class CBOR::Lexer
Token::MapT.new Token::MapT.new
when 0xc0..0xdb when 0xc0..0xdb
consume_tag(read_size(byte - 0xc0)) consume_tag(read_size(byte - 0xc0))
##################
when 0xe0..0xf8 when 0xe0..0xf8
consume_simple_value(read_size(byte - 0xe0)) consume_simple_value(read_size(byte - 0xe0))
when 0xf9
raise ParseError.new("Half-precision floating points are not supported")
when 0xfa
Token::FloatT.new(value: read(Float32))
when 0xfb
Token::FloatT.new(value: read(Float64))
else else
raise ParseError.new("Unexpected first byte 0x#{byte.to_s(16)}") raise ParseError.new("Unexpected first byte 0x#{byte.to_s(16)}")
end end

View File

@ -6,6 +6,10 @@ enum CBOR::Tag : UInt32
Decimal Decimal
BigFloat BigFloat
CSOEEnCrypt = 16
CSOEMac
CSOESign
ConvertBase64URL = 21 ConvertBase64URL = 21
ConvertBase64 ConvertBase64
ConvertBase16 ConvertBase16
@ -16,6 +20,7 @@ enum CBOR::Tag : UInt32
Base64 Base64
RegularExpression RegularExpression
MimeMessage MimeMessage
UUID
CBORMarker = 55799 CBORMarker = 55799
end end