Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/StructUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1290,8 +1290,9 @@ struct FixedArrayClosure{A,S}
end

function (f::FixedArrayClosure{A,S})(_, v) where {A,S}
val, st = make(f.style, eltype(f.arr), v)
i = f.idx[]
i <= length(f.arr) || throw(DimensionMismatch("too many elements for fixed-size array"))
val, st = make(f.style, eltype(f.arr), v)
@inbounds f.arr[i] = val
f.idx[] = i + 1
return st
Expand All @@ -1312,7 +1313,9 @@ function makearray(style, ::Type{T}, source) where {T}
buf = reshape(data, dims)
st = applyeach(style, MultiDimClosure(style, buf, ones(Int, N), Ref(N)), source)
else
st = applyeach(style, FixedArrayClosure(data, style, Ref(1)), source)
idx = Ref(1)
st = applyeach(style, FixedArrayClosure(data, style, idx), source)
idx[] == L + 1 || throw(DimensionMismatch("too few elements for fixed-size array"))
end
return arrayfromdata(T, data, dims), st
else
Expand Down
37 changes: 37 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
using Test, Dates, UUIDs, StructUtils

struct TestStyle <: StructUtils.StructStyle end
struct FixedVectorStyle <: StructUtils.StructStyle
seen::Vector{String}
end
StructUtils.lowerkey(::FixedVectorStyle, k) = string(k)
StructUtils.defaultstate(::FixedVectorStyle) = :fixed_vector
function StructUtils.lift(st::FixedVectorStyle, ::Type{Int}, x::String)
push!(st.seen, x)
return parse(Int, x), :lifted
end
struct StrictUnknownFieldStyle <: StructUtils.StructStyle end
struct UnknownFieldTestError <: Exception
target::Any
Expand Down Expand Up @@ -654,6 +663,34 @@ end
@test StructUtils.make(Vector{SVector{2,Int}}, [[1, 2], [3, 4]]) == [SVector{2,Int}((1, 2)), SVector{2,Int}((3, 4))]
end

@testset "fixed-size vector input length" begin
for V in (SVector, MVector), E in (Int, String)
values = E === Int ? [1, 2] : ["a", "b"]
T = V{2,E}
@test StructUtils.make(T, values) == T(values)
@test_throws DimensionMismatch StructUtils.make(T, values[1:1])
@test_throws DimensionMismatch StructUtils.make(T, vcat(values, values[1:1]))
@test StructUtils.make(V{0,E}, E[]) == V{0,E}()
@test_throws DimensionMismatch StructUtils.make(V{0,E}, values)
end
for n in (1, 2, 3)
visits = Ref(0)
source = (x for x in Iterators.filter(x -> (visits[] += 1; true), 1:n))
@test Base.IteratorSize(typeof(source)) isa Base.SizeUnknown
if n == 2
@test StructUtils.make(SVector{2,Int}, source) == SVector(1, 2)
else
@test_throws DimensionMismatch StructUtils.make(SVector{2,Int}, source)
end
@test visits[] == n
end
style = FixedVectorStyle(String[])
result, state = StructUtils.make(style, SVector{2,Int}, ["1", "2"])
@test result == SVector(1, 2)
@test state === :fixed_vector
@test style.seen == ["1", "2"]
end

@testset "absent fields take the null their type admits" begin
NT = NamedTuple{(:a, :b),Tuple{Union{Missing,Int},Union{Missing,String}}}
@test isequal(StructUtils.make(NT, Dict("a" => 1)), (a=1, b=missing))
Expand Down
Loading