diff --git a/spec/cbor/lexer_spec.cr b/spec/cbor/lexer_spec.cr index 07a5d8a..80edc10 100644 --- a/spec/cbor/lexer_spec.cr +++ b/spec/cbor/lexer_spec.cr @@ -2,33 +2,35 @@ require "../spec_helper" describe CBOR::Lexer do describe "examples from the RFC7049 Appendix A" do - tests : Array(Tuple(String, Bytes)) = [ - {"0", [0x00]}, - {"1", [0x01]}, - # {"10", "0a"}, - # {"23", "17"}, - # {"24", "18 18"}, - # {"25", "18 19"}, - # {"100", "18 64"}, - # {"1000", "19 03 e8"}, - # {"1000000", "1a 00 0f 42 40"}, - # {"1000000000000", "1b 00 00 00 e8 d4 a5 10 00"}, - # {"18446744073709551615", "1b ff ff ff ff ff ff ff ff"}, - # {"18446744073709551616", "c2 49 01 00 00 00 00 00 00 0000"}, - # {"-18446744073709551616", "3b ff ff ff ff ff ff ff ff"}, + tests = [ + {"0", "00"}, + {"1", "01"}, + {"10", "0a"}, + {"23", "17"}, + {"24", "18 18"}, + {"25", "18 19"}, + {"100", "18 64"}, + {"1000", "19 03 e8"}, + {"1000000", "1a 00 0f 42 40"}, + {"1000000000000", "1b 00 00 00 e8 d4 a5 10 00"}, + {"18446744073709551615", "1b ff ff ff ff ff ff ff ff"}, + # {"18446744073709551616", "c2 49 01 00 00 00 00 00 00 00 00"}, + {"-18446744073709551616", "3b ff ff ff ff ff ff ff ff"}, # {"-18446744073709551617", "c3 49 01 00 00 00 00 00 00 00 00"}, - # {"-1", "20"}, - # {"-10", "29"}, - # {"-100", "38 63"}, - # {"-1000", "39 03 e7"}, + {"-1", "20"}, + {"-10", "29"}, + {"-100", "38 63"}, + {"-1000", "39 03 e7"}, ] tests.each do |tt| - it "Reads #{tt[1].inspect} as #{tt[0]}" do - lexer = CBOR::Lexer.new(tt[1]) + debug, hex = tt + it "Reads #{hex} as #{debug}" do + bytes = hex.split.map(&.to_u8(16)) + lexer = CBOR::Lexer.new(Slice.new(bytes.to_unsafe, bytes.size)) token = lexer.read_token - CBOR::Token.to_s(token).should eq(tt[0]) + CBOR::Token.to_s(token).should eq(debug) end end end diff --git a/spec/cbor_spec.cr b/spec/cbor_spec.cr index 844aab6..4d6dc79 100644 --- a/spec/cbor_spec.cr +++ b/spec/cbor_spec.cr @@ -2,8 +2,4 @@ require "./spec_helper" describe CBOR do # TODO: Write tests - - it "works" do - false.should eq(true) - end end diff --git a/src/cbor/lexer.cr b/src/cbor/lexer.cr index 8da4221..53261ff 100644 --- a/src/cbor/lexer.cr +++ b/src/cbor/lexer.cr @@ -51,27 +51,31 @@ class CBOR::Lexer when 0x00..0x17 consume_int(current_byte) when 0x18 - consume_int(read(Uint8)) + consume_int(read(UInt8)) when 0x19 - consume_int(read(Uint16)) + consume_int(read(UInt16)) when 0x1a - consume_int(read(Uint32)) + consume_int(read(UInt32)) when 0x1b - consume_int(read(Uint64)) + consume_int(read(UInt64)) when 0x20..0x37 - consume_int(flip(current_byte.to_i8)) + # This range represents values from -1..-24 so we subtract 0x20 + # from the uint8 value to + consume_int(to_negative_int(current_byte.to_u8 - 0x20)) when 0x38 - consume_int(flip(read(Uint8).to_i8)) + consume_int(to_negative_int(read(UInt8))) when 0x39 - consume_int(flip(read(Uint16).to_i16)) + consume_int(to_negative_int(read(UInt16))) when 0x3a - consume_int(flip(read(Uint32).to_i32)) + consume_int(to_negative_int(read(UInt32))) when 0x3b - consume_int(flip(read(Uint64).to_i64)) + consume_int(to_negative_int(read(UInt64))) + else + fail end end - private def next_byte : Uint8 + private def next_byte : UInt8 byte = @io.read_byte @byte_number += 1 fail unless byte @@ -82,9 +86,24 @@ class CBOR::Lexer Token::IntT.new(@current_byte_number, value) end - private def flip(value) - -1 - value - end + {% begin %} + {% uints = %w(UInt8 UInt16 UInt32 UInt64) %} + {% conv = %w(to_i8 to_i16 to_i32 to_i64 to_i128) %} + + {% for uint, index in uints %} + # Reads the `{{uint.id}}` as a negative integer, returning the samllest + # integer capable of containing the value. + def to_negative_int(value : {{uint.id}}) + int = begin + -value.{{conv[index].id}} + rescue OverflowError + -value.{{conv[index + 1].id}} + end + + int - 1 + end + {% end %} + {% end %} private def read(type : T.class) forall T @byte_number += sizeof(T) diff --git a/src/cbor/token.cr b/src/cbor/token.cr index 118c840..6484e55 100644 --- a/src/cbor/token.cr +++ b/src/cbor/token.cr @@ -3,7 +3,7 @@ class CBOR::Token record BoolT, byte_number : Int32, value : Bool record ArrayT, byte_number : Int32, size : UInt32 record MapT, byte_number : Int32, size : UInt32 - record IntT, byte_number : Int32, value : Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 + record IntT, byte_number : Int32, value : Int8 | UInt8 | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Int128 record FloatT, byte_number : Int32, value : Float64 record StringT, byte_number : Int32, value : String record BytesT, byte_number : Int32, value : Bytes