diff --git a/src/StaticArrays.jl b/src/StaticArrays.jl index 64ba7915..c7ebe692 100644 --- a/src/StaticArrays.jl +++ b/src/StaticArrays.jl @@ -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 @@ -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") diff --git a/src/io.jl b/src/io.jl new file mode 100644 index 00000000..591408ed --- /dev/null +++ b/src/io.jl @@ -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 + diff --git a/test/io.jl b/test/io.jl new file mode 100644 index 00000000..3bf9f9a6 --- /dev/null +++ b/test/io.jl @@ -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 + diff --git a/test/runtests.jl b/test/runtests.jl index 94c6e0f5..d0ec974b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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