Skip to content

Commit

Permalink
Implement read() write() and read!() for static arrays
Browse files Browse the repository at this point in the history
Unfortunately these allocate, but there doesn't seem to be a way to
avoid this yet, until the compiler can allocate Base.RefValue on the
stack (even Base.read(io, Float64) allocates!)
  • Loading branch information
Chris Foster committed May 2, 2017
1 parent df19477 commit 10d18ab
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/StaticArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Base: getindex, setindex!, size, similar, vec, show,
fill!, det, inv, eig, eigvals, trace, vecnorm, norm, dot, diagm,
sum, diff, prod, count, any, all, sumabs, sumabs2, minimum,
maximum, extrema, mean, copy, rand, randn, randexp, rand!, randn!,
randexp!, normalize, normalize!
randexp!, normalize, normalize!, read, read!, write

export StaticScalar, StaticArray, StaticVector, StaticMatrix
export Scalar, SArray, SVector, SMatrix
Expand Down Expand Up @@ -92,6 +92,7 @@ include("solve.jl")
include("eigen.jl")
include("cholesky.jl")
include("deque.jl")
include("io.jl")

include("FixedSizeArrays.jl")
include("ImmutableArrays.jl")
Expand Down
18 changes: 18 additions & 0 deletions src/io.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

@inline function read(io::IO, ::Type{SA}) where {SA<:StaticArray}
# Copy Base implementation of `read` for primitive types. This is less
# efficient in 0.6 that we'd like because creating the Ref allocates.
elements = Ref{NTuple{length(SA),eltype(SA)}}()
read(io, elements)
SA(elements[])
end

@inline function read!(io::IO, a::SA) where {SA<:StaticArray}
unsafe_read(io, Base.unsafe_convert(Ptr{eltype(SA)}, a), sizeof(a))
a
end

@inline function write(io::IO, a::SA) where {SA<:StaticArray}
write(io, Ref(Tuple(a)))
end

37 changes: 37 additions & 0 deletions test/io.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Serialize `xs` as type `T` to an IOBuffer one by one using Base.write.
# Return the buffer positioned at the start, ready for reading
write_buf(::Type{T}, xs...) where {T} = write_buf(map(T, xs)...)

function write_buf(xs...)
io = IOBuffer()
foreach(x->write(io, x), xs)
seek(io, 0)
io
end

@testset "Binary IO" begin
@testset "read" begin
# Read static arrays from a stream which was serialized elementwise
@test read(write_buf(UInt8, 1,2,3), SVector{3,UInt8}) === SVector{3,UInt8}(1,2,3)
@test read(write_buf(Int32, -1,2,3), SVector{3,Int32}) === SVector{3,Int32}(-1,2,3)
@test read(write_buf(Float64, 1,2,3), SVector{3,Float64}) === SVector{3,Float64}(1,2,3)
@test read(write_buf(Float64, 1,2,3,4), SMatrix{2,2,Float64}) === @SMatrix [1.0 3.0; 2.0 4.0]
end

@testset "write" begin
# Compare serialized bytes
@test take!(write_buf(UInt8, 1,2,3)) == take!(write_buf(SVector{3,UInt8}(1,2,3)))
@test take!(write_buf(Int32, -1,2,3)) == take!(write_buf(SVector{3,Int32}(-1,2,3)))
@test take!(write_buf(Float64, 1,2,3)) == take!(write_buf(SVector{3,Float64}(1,2,3)))
@test take!(write_buf(Float64, 1,2,3,4)) == take!(write_buf(@SMatrix [1.0 3.0; 2.0 4.0]))
end

@testset "read!" begin
# Read static arrays from a stream which was serialized elementwise
@test read!(write_buf(UInt8, 1,2,3), zeros(MVector{3,UInt8})) == MVector{3,UInt8}(1,2,3)
@test read!(write_buf(Int32, -1,2,3), zeros(MVector{3,Int32})) == MVector{3,Int32}(-1,2,3)
@test read!(write_buf(Float64, 1,2,3), zeros(MVector{3,Float64})) == MVector{3,Float64}(1,2,3)
@test read!(write_buf(Float64, 1,2,3,4), zeros(MMatrix{2,2,Float64})) == @MMatrix [1.0 3.0; 2.0 4.0]
end
end

2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ using Base.Test
include("solve.jl") # Strange inference / world-age error
include("eigen.jl")
include("deque.jl")
include("io.jl")

include("fixed_size_arrays.jl")
end

0 comments on commit 10d18ab

Please sign in to comment.