WIP: Array
parent
839a41dd84
commit
74c71a57c3
|
@ -21,6 +21,14 @@ describe "CBOR helpers on basic types" do
|
|||
{Nil, Bytes[0xf7], nil},
|
||||
{Float32, Bytes[0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a], 1.1_f32},
|
||||
{Float64, Bytes[0xfa, 0x47, 0xc3, 0x50, 0x00], 100000.0_f64},
|
||||
{Array(Int8), Bytes[0x83, 0x01, 0x02, 0x03], [1_i8, 2_i8, 3_i8]},
|
||||
{Array(Array(Int8) | Int8),
|
||||
Bytes[0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05],
|
||||
[1_i8, [2_i8, 3_i8], [4_i8, 5_i8]]},
|
||||
{Array(UInt8), Bytes[0x9f, 0xff], [] of UInt8},
|
||||
# {Array(Array(Int8) | Int8),
|
||||
# Bytes[0x9f, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff],
|
||||
# [1_i8, [2_i8, 3_i8], [4_i8, 5_i8]]},
|
||||
]
|
||||
|
||||
tests.each do |tt|
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class CBOR::Decoder
|
||||
@lexer : Lexer
|
||||
@current_token : Token::T?
|
||||
getter current_token : Token::T?
|
||||
|
||||
def initialize(input)
|
||||
@lexer = Lexer.new(input)
|
||||
|
@ -70,10 +70,27 @@ class CBOR::Decoder
|
|||
end
|
||||
end
|
||||
|
||||
def consume_array(&block)
|
||||
read_type(Token::ArrayT, finish_token: false) do |token|
|
||||
read(token.size) { yield }
|
||||
end
|
||||
end
|
||||
|
||||
private def finish_token!
|
||||
@current_token = @lexer.next_token
|
||||
end
|
||||
|
||||
def read(size : Int32?, &block)
|
||||
if size
|
||||
size.times { yield }
|
||||
else
|
||||
@lexer.until_break do |token|
|
||||
@current_token = token
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private macro read_type(type, finish_token = true, ignore_tag = true, &block)
|
||||
# Skip the tag unless the token we want to read is a tag
|
||||
{% if ignore_tag %}
|
||||
|
|
|
@ -39,6 +39,12 @@ def Slice.new(decoder : CBOR::Decoder)
|
|||
decoder.read_bytes.to_slice
|
||||
end
|
||||
|
||||
def Array.new(decoder : CBOR::Decoder)
|
||||
arr = new
|
||||
decoder.consume_array { arr << T.new(decoder) }
|
||||
arr
|
||||
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].
|
||||
#
|
||||
|
@ -58,3 +64,52 @@ def Time.new(decoder : CBOR::Decoder)
|
|||
raise CBOR::ParseError.new("Expected tag to have value 0 or 1, got #{tag.value.to_s}")
|
||||
end
|
||||
end
|
||||
|
||||
def Union.new(decoder : CBOR::Decoder)
|
||||
token = decoder.current_token
|
||||
|
||||
# Optimization: use fast path for primitive types
|
||||
{% begin %}
|
||||
# Here we store types that are not primitive types
|
||||
{% non_primitives = [] of Nil %}
|
||||
|
||||
{% for type, index in T %}
|
||||
{% if type == Nil %}
|
||||
return decoder.read_nil if token.is_a?(CBOR::Token::SimpleValueT)
|
||||
{% elsif type == Bool %}
|
||||
return decoder.read_bool if token.is_a?(CBOR::Token::SimpleValueT)
|
||||
{% elsif type == String %}
|
||||
return decoder.read_string if token.is_a?(CBOR::Token::StringT)
|
||||
{% elsif type == Int8 || type == Int16 || type == Int32 || type == Int64 ||
|
||||
type == UInt8 || type == UInt16 || type == UInt32 || type == UInt64 %}
|
||||
return {{type}}.new(decoder) if token.is_a?(CBOR::Token::IntT)
|
||||
{% elsif type == Float32 || type == Float64 %}
|
||||
return {{type}}.new(decoder) if token.is_a?(CBOR::Token::FloatT)
|
||||
{% unless T.any? { |t| t < Int } %}
|
||||
return {{type}}.new(decoder) if token.is_a?(CBOR::Token::IntT)
|
||||
{% end %}
|
||||
{% else %}
|
||||
{% non_primitives << type %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
# If after traversing all the types we are left with just one
|
||||
# non-primitive type, we can parse it directly (no need to use `read_raw`)
|
||||
{% if non_primitives.size == 1 %}
|
||||
return {{non_primitives[0]}}.new(decoder)
|
||||
{% else %}
|
||||
raise "What is this?"
|
||||
# node = decoder.read_node
|
||||
# {% for type in non_primitives %}
|
||||
# unpacker = CBOR::NodeUnpacker.new(node)
|
||||
# begin
|
||||
# return {{type}}.new(unpacker)
|
||||
# rescue e : CBOR::TypeCastError
|
||||
# # ignore
|
||||
# end
|
||||
# {% end %}
|
||||
# {% end %}
|
||||
{% end %}
|
||||
|
||||
raise CBOR::ParseError.new("Couldn't parse data as " + {{T.stringify}})
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue