diff --git a/spec/cbor/from_cbor_spec.cr b/spec/cbor/from_cbor_spec.cr index fcb6bc2..56f6f3a 100644 --- a/spec/cbor/from_cbor_spec.cr +++ b/spec/cbor/from_cbor_spec.cr @@ -37,6 +37,7 @@ describe "CBOR helpers on basic types" do {Hash(UInt8, UInt8), Bytes[0xa0], {} of UInt8 => UInt8}, {Hash(UInt8, UInt8), Bytes[0xa2, 0x01, 0x02, 0x03, 0x04], Hash(UInt8, UInt8){1 => 2, 3 => 4}}, {TestEnum, Bytes[0x1a, 0x00, 0x00, 0x00, 0x01], TestEnum::Foo}, + {Tuple(Int8, Int8), Bytes[0x82, 0x01, 0x02], {1_i8, 2_i8}}, ] tests.each do |tt| diff --git a/src/cbor/from_cbor.cr b/src/cbor/from_cbor.cr index 62fcfb7..43a2a3d 100644 --- a/src/cbor/from_cbor.cr +++ b/src/cbor/from_cbor.cr @@ -73,6 +73,32 @@ def Enum.new(decoder : CBOR::Decoder) end end +def Tuple.new(decoder : CBOR::Decoder) + {% begin %} + token = decoder.current_token + unless token.is_a?(CBOR::Token::ArrayT) + raise decoder.unexpected_token(token, "ArrayT") + end + + size = token.size + + raise CBOR::ParseError.new("Cannot read indefinite size array as Tuple") unless size + + unless {{ @type.size }} <= size + raise CBOR::ParseError.new("Expected array with size #{ {{ @type.size }} }, but got #{size}") + end + decoder.finish_token! + + value = Tuple.new( + {% for i in 0...@type.size %} + (self[{{i}}].new(decoder)), + {% end %} + ) + + value + {% end %} +end + # Reads the CBOR values as a time. The value must be surrounded by a time tag as # specified by [Section 2.4.1 of RFC 7049][1]. #