Can somebody help with this case?
## I've started with reinterpreting some complex types from a binary stream:
bytevec = UInt8[0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00]
reinterpret(Tuple{Int8, Int16, Int32}, bytevec)
# but seems like because of structure alignment I cannot just read
# any combination of bitstypes from "packed" binary data
sizeof(bytevec) != sizeof(Tuple{Int8, Int16, Int32}) # 7 != 8
# What I want is to read structured data from a binary stream into a tuple:
io = IOBuffer(bytevec)
result = (read(io, Int8), read(io, Int16), read(io, Int32))
#1 The problem is, I cannot hardcode types, because there are variable combinations of types, known at runtime. So I need to generate a code that gathers several reads with appropriate types into a tuple. So, I’m writing a macro for that:
macro read_schema(io, Ts...)
args = map(T -> :(read($io, $T)), Ts)
:(tuple($(args...)))
end
# this works as expected:
bytevec = UInt8[0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00]
io = IOBuffer(bytevec)
@read_schema(io, Int8, Int16, Int32)
# But then I need to write type info inside a tuple variable.
# And for some reason tuple desctructuring is not working properly with macro:
types = (Int8, Int16, Int32)
io = IOBuffer(bytevec)
@read_schema(io, types...)
ERROR: MethodError: no method matching read(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Type{Int8}, ::Type{Int16}, ::Type{Int32})
#2 Another approach I tried with generated function, taken StructArrays as example:
@generated function read_schema_gen(io::IOBuffer, types::Type...)
Expr(:tuple, [Expr(:call, :read, :io, t) for t in types]...)
end
bytevec = UInt8[0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00]
io = IOBuffer(bytevec)
types = (Int8, Int16, Int32)
read_schema_gen(io, types...)
ERROR: The IO stream does not support reading objects of type Type{Int8}.
I don’t understand, what’s wrong with approaches #1 and #2, and how to fix that?