From e7f4426062c6459aa52f6535a5cb319c5400e65f Mon Sep 17 00:00:00 2001 From: Alberto Restifo Date: Thu, 23 Apr 2020 23:25:28 +0200 Subject: [PATCH] Implement simple values --- spec/rfc_spec.cr | 24 ++++++++++++------------ src/cbor/diagnostic.cr | 7 ++++--- src/cbor/lexer.cr | 17 ++++++++++------- src/cbor/simple_value.cr | 21 +++++++++++++++++++++ src/cbor/tag.cr | 40 ++++++++++++++++++++-------------------- src/cbor/token.cr | 12 +++++------- 6 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 src/cbor/simple_value.cr diff --git a/spec/rfc_spec.cr b/spec/rfc_spec.cr index 6cf00be..5c32fe7 100644 --- a/spec/rfc_spec.cr +++ b/spec/rfc_spec.cr @@ -51,19 +51,19 @@ tests = [ # { %(Infinity), "fb 7f f0 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" }, - # { %(false), "f4" }, - # { %(true), "f5" }, - # { %(null), "f6" }, - # { %(undefined), "f7" }, - # { %(simple(16)), "f0" }, - # { %(simple(24)), "f8 18" }, - # { %(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" }, + { %(false), "f4" }, + { %(true), "f5" }, + { %(null), "f6" }, + { %(undefined), "f7" }, + { %(simple(16)), "f0" }, + { %(simple(24)), "f8 18" }, + { %(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" }, - # { %(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" }, + { %(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" }, { %(h''), "40" }, { %(h'01020304'), "44 01 02 03 04" }, { %(""), "60" }, diff --git a/src/cbor/diagnostic.cr b/src/cbor/diagnostic.cr index 97042f2..befa983 100644 --- a/src/cbor/diagnostic.cr +++ b/src/cbor/diagnostic.cr @@ -50,9 +50,10 @@ class CBOR::Diagnostic hash_body = read_hash(token.size).join(", ") return "{#{hash_body}}" if token.size "{_ #{hash_body}}" - when Token::BoolT - return "true" if token.value - "false" + when Token::SimpleValueT + token.value.to_diagnostic + when Token::TagT + "#{token.value.value.to_s}(#{next_value})" else token.inspect end diff --git a/src/cbor/lexer.cr b/src/cbor/lexer.cr index 60ea3c4..7233a99 100644 --- a/src/cbor/lexer.cr +++ b/src/cbor/lexer.cr @@ -82,10 +82,8 @@ class CBOR::Lexer when 0xc0..0xdb consume_tag(read_size(byte - 0xc0)) ################## - when 0xf4 - Token::BoolT.new(value: false) - when 0xf5 - Token::BoolT.new(value: true) + when 0xe0..0xf8 + consume_simple_value(read_size(byte - 0xe0)) else raise ParseError.new("Unexpected first byte 0x#{byte.to_s(16)}") end @@ -172,9 +170,14 @@ class CBOR::Lexer Token::MapT.new(size: size.to_i32) end - private def consume_tag(size) : Token::TagT - raise ParseError.new("Maximum size for tag exceeded") if size > UInt32::MAX - Token::TagT.new(id: size.to_u32) + private def consume_tag(id) : Token::TagT + raise ParseError.new("Maximum size for tag ID exceeded") if id > UInt32::MAX + Token::TagT.new(value: Tag.new(id.to_u32)) + end + + private def consume_simple_value(id) : Token::SimpleValueT + raise ParseError.new("Invalid simple value #{id.to_s}") if id > 255 + Token::SimpleValueT.new(value: SimpleValue.new(id.to_u8)) end # Creates a method overloaded for each UInt sizes to convert the UInt into diff --git a/src/cbor/simple_value.cr b/src/cbor/simple_value.cr new file mode 100644 index 0000000..a931d9d --- /dev/null +++ b/src/cbor/simple_value.cr @@ -0,0 +1,21 @@ +enum CBOR::SimpleValue : UInt8 + False = 20 + True + Null + Undefined + + def to_diagnostic : String + case self + when False + "false" + when True + "true" + when Null + "null" + when Undefined + "undefined" + else + "simple(#{self.value.to_s})" + end + end +end diff --git a/src/cbor/tag.cr b/src/cbor/tag.cr index 9e27977..79fe467 100644 --- a/src/cbor/tag.cr +++ b/src/cbor/tag.cr @@ -1,21 +1,21 @@ -module CBOR::Tag - enum Kind - Unassigned - RFC3339Time - EpochTime - PositiveBigNum - NegativeBigNum - DecimalFraction - BigFloat - ExpectBase64URLConversion - ExpectBase64Conversion - ExpectBase16Conversion - EncodedCBOR - URI - Base64URL - Base64 - RegularExpresion - MIME - SelfDescribeCBOR - end +enum CBOR::Tag : UInt32 + RFC3339Time + EpochTime + PositiveBigNum + NegativeBigNum + Decimal + BigFloat + + ConvertBase64URL = 21 + ConvertBase64 + ConvertBase16 + CBOREncoded + + URI = 32 + Base64URL + Base64 + RegularExpression + MimeMessage + + CBORMarker = 55799 end diff --git a/src/cbor/token.cr b/src/cbor/token.cr index 5846e16..ed8551a 100644 --- a/src/cbor/token.cr +++ b/src/cbor/token.cr @@ -1,21 +1,19 @@ module CBOR::Token - record NullT, undefined : Bool = false - record BoolT, value : Bool record IntT, value : Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 record FloatT, value : Float32 | Float64 record BytesT, value : Bytes, chunks : Array(Int32)? = nil record StringT, value : String, chunks : Array(Int32)? = nil record ArrayT, size : Int32? = nil record MapT, size : Int32? = nil - record TagT, id : UInt32 + record TagT, value : Tag + record SimpleValueT, value : SimpleValue - alias T = NullT | - BoolT | - IntT | + alias T = IntT | FloatT | BytesT | StringT | ArrayT | MapT | - TagT + TagT | + SimpleValueT end