diff --git a/spec/types/bytes_array_spec.cr b/spec/types/bytes_array_spec.cr new file mode 100644 index 0000000..4898890 --- /dev/null +++ b/spec/types/bytes_array_spec.cr @@ -0,0 +1,29 @@ +require "../spec_helper" + +describe CBOR::BytesArray do + describe "#to_bytes" do + it "converts to bytes" do + arr = CBOR::BytesArray.new + arr << Bytes[0xff, 0xff] + arr << Bytes[0xee, 0xee] + + bytes = arr.to_bytes + bytes.size.should eq(4) + bytes.should eq(Bytes[0xff, 0xff, 0xee, 0xee]) + end + + it "can be called more than ocne" do + arr = CBOR::BytesArray.new + arr << Bytes[0xff, 0xff] + arr << Bytes[0xee, 0xee] + + bytes1 = arr.to_bytes + bytes1.size.should eq(4) + bytes1.should eq(Bytes[0xff, 0xff, 0xee, 0xee]) + + bytes2 = arr.to_bytes + bytes2.size.should eq(4) + bytes2.should eq(Bytes[0xff, 0xff, 0xee, 0xee]) + end + end +end diff --git a/src/cbor.cr b/src/cbor.cr index 8418855..d6bc043 100644 --- a/src/cbor.cr +++ b/src/cbor.cr @@ -19,5 +19,6 @@ module CBOR UInt32 | Int64 | UInt64 | - Int128 + Int128 | + BytesArray end diff --git a/src/cbor/diagnostic.cr b/src/cbor/diagnostic.cr index c1f6869..4eaaa33 100644 --- a/src/cbor/diagnostic.cr +++ b/src/cbor/diagnostic.cr @@ -16,7 +16,7 @@ class CBOR::Diagnostic def to_s : String result = "" while value = next_value - result << value + result += value end result end @@ -26,10 +26,14 @@ class CBOR::Diagnostic return nil unless token case token[:kind] + when Kind::Int + token[:value].to_s + when Kind::Bytes + "h'#{token[:value].as(Bytes).hexstring}'" when Kind::BytesArray - BytesArray.new(token[:value]).to_diagnostics + token[:value].as(BytesArray).to_diagnostic else - Token.do_diagnostics(token) + token[:kind].to_s end end end diff --git a/src/cbor/lexer.cr b/src/cbor/lexer.cr index 8586952..58b81bb 100644 --- a/src/cbor/lexer.cr +++ b/src/cbor/lexer.cr @@ -51,7 +51,7 @@ class CBOR::Lexer end # Consumes the bytes array until it reaches a break - def read_bytes_array : Bytes + def read_bytes_array : CBOR::BytesArray bytes = BytesArray.new loop do @@ -59,10 +59,10 @@ class CBOR::Lexer raise ParseError.new("Unexpected EOF while reading bytes array") unless token break if token[:kind] == Kind::BytesArrayEnd raise ParseError.new("Illegal token #{token.class} while reading bytes array") unless token[:kind] == Kind::Bytes - bytes << token[:value].as(UInt8) + bytes << token[:value].as(Bytes) end - bytes.to_bytes + bytes end private def next_token : Token? diff --git a/src/cbor/token.cr b/src/cbor/token.cr index 462324d..5a5b44d 100644 --- a/src/cbor/token.cr +++ b/src/cbor/token.cr @@ -13,38 +13,6 @@ enum CBOR::Kind Array ArrayEnd Map - - def to_diagnostic : String - case self - when Int - token.value.to_s - when Bytes - return %(h'') if token.value.empty? - "h'#{token.value.hexstring}'" - when Null - "null" - when Undefined - "undefined" - when BoolT - token.value.to_s - when BytesArray - "(_ " - when BytesArrayEnd - ")" - when Float - "TODO" - when String - "TODO" - when StringArray - "TODO" - when Map - "TODO" - when Array - "TODO" - else - raise "Uknown diagnostics representation for #{self.to_s}" - end - end end alias CBOR::Token = NamedTuple(kind: Kind, value: Type) diff --git a/src/cbor/type/bytes_array.cr b/src/cbor/type/bytes_array.cr index 8cbc9be..e13640a 100644 --- a/src/cbor/type/bytes_array.cr +++ b/src/cbor/type/bytes_array.cr @@ -1,21 +1,23 @@ -class CBOR::BytesArray < Array(UInt8) - def self.new(bytes : Bytes) - new(bytes.to_a) - end - - def to_a : Array(UInt8) - self.as(Array(UInt8)) - end - +class CBOR::BytesArray < Array(Bytes) def to_bytes : Bytes - Bytes.new(self.to_unsafe, self.size) + size = reduce(0) { |acc, chunk| acc + chunk.size } + bytes = Bytes.new(size) + + # Copy each chunk into the new bytes slice + ptr = bytes.to_unsafe + each do |chunk| + chunk.copy_to(ptr, chunk.size) + ptr += chunk.size + end + + bytes end def to_diagnostic : String - "(_ #{map(&to_byte_diagnostic).join(", ")})" + "(_ #{map { |chunk| to_byte_diagnostic(chunk) }.join(", ")})" end - private def to_byte_diagnostic(i : UInt8) : String - "h'#{i.hexstring}'" + private def to_byte_diagnostic(chunk : Bytes) : String + "h'#{chunk.hexstring}'" end end