85 lines
2.1 KiB
Crystal
85 lines
2.1 KiB
Crystal
# Reads a CBOR input into a diagnostic string.
|
|
# This consumes the IO and is mostly usedful to tests again the example
|
|
# provided in the RFC and ensuring a correct functioning of the `CBOR::Lexer`.
|
|
class CBOR::Diagnostic
|
|
@lexer : Lexer
|
|
|
|
def initialize(input)
|
|
@lexer = Lexer.new(input)
|
|
end
|
|
|
|
# Reads the content of the IO and prints out a diagnostic string
|
|
# represation of the input.
|
|
def to_s : String
|
|
result = ""
|
|
while value = next_value
|
|
result += value
|
|
end
|
|
result
|
|
end
|
|
|
|
private def next_value : String?
|
|
token = @lexer.read_next
|
|
return nil unless token
|
|
to_diagnostic(token)
|
|
end
|
|
|
|
private def to_diagnostic(token : Token) : String
|
|
case token.kind
|
|
when Kind::Int
|
|
token.value.to_s
|
|
when Kind::String
|
|
if token.chunks
|
|
chunks = chunks(token.value.as(String), token.chunks.as(Array(Int32)))
|
|
"(_ #{chunks.map { |s| string(s) }.join(", ")})"
|
|
else
|
|
string(token.value.as(String))
|
|
end
|
|
when Kind::Bytes
|
|
if token.chunks
|
|
chunks = chunks(token.value.as(Bytes), token.chunks.as(Array(Int32)))
|
|
"(_ #{chunks.map { |b| bytes(b) }.join(", ")})"
|
|
else
|
|
bytes(token.value.as(Bytes))
|
|
end
|
|
# when Kind::Array
|
|
# value = token.value.as(Array(Type))
|
|
# return "[]" unless value.size > 0
|
|
|
|
# content = value.map { |token| to_diagnostic(token) }.join(", ")
|
|
|
|
# return "[#{content}]" if token.size
|
|
# "[_ #{content}]"
|
|
else
|
|
token.kind.to_s
|
|
end
|
|
end
|
|
|
|
private def chunks(value : Bytes, chunks : Array(Int32)) : Array(Bytes)
|
|
res = Array(Bytes).new
|
|
bytes = value.to_a
|
|
chunks.each do |size|
|
|
bytes_chunk = bytes.shift(size)
|
|
res << Bytes.new(bytes_chunk.to_unsafe, bytes_chunk.size)
|
|
end
|
|
res
|
|
end
|
|
|
|
private def chunks(value : String, chunks : Array(Int32)) : Array(String)
|
|
res = Array(String).new
|
|
arr = value.split("")
|
|
chunks.each do |size|
|
|
res << arr.shift(size).join
|
|
end
|
|
res
|
|
end
|
|
|
|
private def bytes(b : Bytes) : String
|
|
"h'#{b.hexstring}'"
|
|
end
|
|
|
|
private def string(s : String) : String
|
|
%("#{s}")
|
|
end
|
|
end
|