I have a packed structure of data in a binary stream that I wish to
read in julia. I defined the type struct and then added a read
method
to dispatch for that type:
struct MyStruct
A::Int16
B::Int16
C::Int64
D::Int16
E::Int16
F::UInt32
end
import Base.read
function read(s::IO, ::Type{Caen_v20_0x1})
a = Base.read(s, Int16)
b = Base.read(s, Int16)
c = Base.read(s, Int64)
d = Base.read(s, Int16)
e = Base.read(s, Int16)
f = Base.read(s, UInt32)
MyStruct(a,b,c,d,e,f)
end
With this I can use read
to read a single MyStruct
value.
val = read(io,MyStruct)
or in a loop with
vMyStruct = Vector{MyStruct}(undef,10)
for i in eachindex(vMyStruct)
vMyStruct[i] = read(io,eltype(vMyStruct))
end
However, when I use read!(io,vMyStruct)
the result is not
equivalent. I looked at the code for read!
and it appears
that the IO is just an unsafe_read
of the binary stream and
not repeated use of the read
method as defined.
Looking at the code for read
in base it seems that the looping
over the read
method is in there but that the check to see if an
unsafe_read
would give the correct result may not be correct.
From io.jl
in base:
function read!(s::IO, a::AbstractArray{T}) where T
if isbitstype(T) && (a isa Array || a isa FastContiguousSubArray{T,<:Any,<:Array{T}})
GC.@preserve a unsafe_read(s, pointer(a), sizeof(a))
else
for i in eachindex(a)
a[i] = read(s, T)
end
end
return a
end
It seems like the FastContiguousSubArray
test maybe should be
&&
instead of ||
which might make the hand loop with eachindex
unneccessary.
I vaguely remember this working the last time I worked with the I/O
but maybe I am misremembering things…
Is this the intended operation for read!
in this case?