Complete basic int conversion

dev
Alberto Restifo 2020-04-19 12:16:05 +02:00
parent 9d1c255c2c
commit a956794f4e
4 changed files with 56 additions and 39 deletions

View File

@ -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

View File

@ -2,8 +2,4 @@ require "./spec_helper"
describe CBOR do
# TODO: Write tests
it "works" do
false.should eq(true)
end
end

View File

@ -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)

View File

@ -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