Start implementing from_cbor decoding
parent
9739c4971b
commit
547e8af2bd
|
@ -0,0 +1,24 @@
|
|||
require "../spec_helper"
|
||||
|
||||
describe "CBOR helpers on basic types" do
|
||||
describe "#from_cbor" do
|
||||
tests = [
|
||||
{String, Bytes[0x61, 0x61], "a"},
|
||||
{UInt8, Bytes[0x18, 0x18], 24},
|
||||
{UInt16, Bytes[0x19, 0x03, 0xe8], 1000},
|
||||
{UInt32, Bytes[0x1a, 0x00, 0x0f, 0x42, 0x40], 1000000},
|
||||
{UInt64, Bytes[0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00], 1000000000000},
|
||||
{Int8, Bytes[0x29], -10},
|
||||
{Bytes, Bytes[0x44, 0x01, 0x02, 0x03, 0x04], Bytes[0x01, 0x02, 0x03, 0x04]},
|
||||
]
|
||||
|
||||
tests.each do |tt|
|
||||
type, bytes, want = tt
|
||||
|
||||
it "decodes #{type.class}" do
|
||||
res = type.from_cbor(bytes)
|
||||
res.should eq(want)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
class CBOR::Decoder
|
||||
@lexer : Lexer
|
||||
@current_token : Token::T?
|
||||
|
||||
def initialize(input)
|
||||
@lexer = Lexer.new(input)
|
||||
@current_token = @lexer.next_token
|
||||
end
|
||||
|
||||
def read_string : String
|
||||
case token = @current_token
|
||||
when Token::StringT
|
||||
finish_token!
|
||||
token.value
|
||||
when Token::BytesT
|
||||
finish_token!
|
||||
String.new(token.value)
|
||||
else
|
||||
unexpected_token(token, "StringT or BytesT")
|
||||
end
|
||||
end
|
||||
|
||||
def read_int
|
||||
read_type(Token::IntT) { |token| token.value }
|
||||
end
|
||||
|
||||
def read_bytes
|
||||
read_type(Token::BytesT) { |token| token.value }
|
||||
end
|
||||
|
||||
private def finish_token!
|
||||
@current_token = @lexer.next_token
|
||||
end
|
||||
|
||||
private macro read_type(type, finish_token = true, &block)
|
||||
case token = @current_token
|
||||
when {{type}}
|
||||
{% if finish_token %}finish_token!{% end %}
|
||||
{{ block.body }}
|
||||
else
|
||||
unexpected_token(token, {{type.stringify.split("::").last}})
|
||||
end
|
||||
end
|
||||
|
||||
private def unexpected_token(token, expected = nil)
|
||||
message = "Unexpected token #{token.class}"
|
||||
message += " expected #{expected}" if expected
|
||||
raise ParseError.new(message)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
def Object.from_cbor(string_or_io)
|
||||
parser = CBOR::Decoder.new(string_or_io)
|
||||
new(parser)
|
||||
end
|
||||
|
||||
def String.new(decoder : CBOR::Decoder)
|
||||
decoder.read_string
|
||||
end
|
||||
|
||||
{% for size in [8, 16, 32, 64] %}
|
||||
|
||||
def Int{{size.id}}.new(decoder : CBOR::Decoder)
|
||||
decoder.read_int.to_i{{size.id}}
|
||||
end
|
||||
|
||||
def UInt{{size.id}}.new(decoder : CBOR::Decoder)
|
||||
decoder.read_int.to_u{{size.id}}
|
||||
end
|
||||
|
||||
{% end %}
|
||||
|
||||
def Slice.new(decoder : CBOR::Decoder)
|
||||
decoder.read_bytes.to_slice
|
||||
end
|
|
@ -1,10 +1,6 @@
|
|||
class CBOR::Lexer
|
||||
BREAK = 0xff
|
||||
|
||||
def self.new(string : String)
|
||||
new IO::Memory.new(string)
|
||||
end
|
||||
|
||||
def self.new(slice : Bytes)
|
||||
new IO::Memory.new(slice)
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue