Suppose I have a immutable struct with primitive fields (e.g., UInt8):
struct MyStruct
field1::UInt8
field2::UInt16
...
end
What is the most efficient method to convert a vector of bytes like
bytes = read(io, 100)
into an instance of the struct?
Do I need to loop over the fields and reinterpret each byte?
I tested with reinterpret(MyStruct, bytes) and it apparently works, but the result is a vector with a single instance. Any way to return just the instance?
My current solution for future reference:
only(reinterpret(MySctruct, bytes))
I'm away from computer, going by memory you can pass a custom type to read
Probably <https://docs.julialang.org/en/v1/base/io-network/#Base.read!>
That is my current solution above, right?
Júlio Hoffimann said:
My current solution for future reference:
only(reinterpret(MySctruct, bytes))
This one :up:
I said read, not reinterpret
Didn't know read also supported this. Let me check...
Would it be that method?
Yes
Regarding the endianness, how can I enforce ntoh to always convert from Big Endian?
That wasn't what I linked actually because zulip messed up the exclamation mark, but that should work too
If I need to enforce endianness, I need to read first with the original endianness, convert the endianess with ntoh, and then reinterpret?
Or there is a direct method with just read + ntoh?
Júlio Hoffimann said:
Regarding the endianness, how can I enforce
ntohto always convert from Big Endian?
If you need to invert the endianess you may have to first rest the raw bits, invert, and then reinterpret
Yep, I think the reinterpret is the way to go then.
Solution for future reference:
only(reinterpret(MyStruct, map(ntoh, bytes)))
The solution above doesn't work. The fact that the file endianness is different than the host machine forces reading field-by-field, converting each field with ntoh and then combining fields into the final struct.
The solution that actually works:
fields = map(fieldnames(MyStruct)) do field
type = fieldtype(MyStruct, field)
ntoh(read(io, type))
end
reinterpret(MyStruct, fields)
Júlio Hoffimann has marked this topic as resolved.
You could also do
ptr = convert(Ptr{MyType}, pointer(bytes))
unsafe_load(ptr)
Make sure you're aware of julia's padding conventions though. E.g. your struct
struct MyStruct
field1::UInt8
field2::UInt16
end
actually has padding between field1 and field2 to give it anlignment, so field2 is not the the 2nd and 3rd bytes of the array.
Thank yo for sharing this alternative. I think I will go with the reinterpret approach as it is working well.
Last updated: Nov 27 2025 at 04:44 UTC