diff --git a/src/container.jl b/src/container.jl index a1d0b83..4186a06 100644 --- a/src/container.jl +++ b/src/container.jl @@ -1,13 +1,18 @@ """ - UndefProperty + UndefProperty{T} Placeholder for undefined properties in [`Container`](@ref). """ -struct UndefProperty end +struct UndefProperty{T} end + +UndefProperty() = UndefProperty{Any}() Base.show(io::IO, ::UndefProperty) = print(io, "#undef") +undeftypeof(::UndefProperty{T}) where {T} = T +undeftypeof(obj) = typeof(obj) + """ Container{T} @@ -22,8 +27,8 @@ Create an uninitialized container for `T`. ```jldoctest julia> Container{Complex{Int64}}() Container{Complex{Int64}}: - re: #undef - im: #undef + re: Int64 = #undef + im: Int64 = #undef ``` """ struct Container{T} @@ -39,7 +44,7 @@ end Base.getproperty(obj::Container{T}, name::Symbol) where {T} = get(getfield(obj, 1), name) do if name in fieldnames(T) - UndefProperty() + UndefProperty{fieldtype(T, name)}() else error("type $T has no field $name") end @@ -73,13 +78,9 @@ function Base.show(io::IO, mime::MIME"text/plain", obj::Container) print(io, " ") print(io, prop) print(io, ": ") - if val isa UndefProperty - show(io, val) - else - show(io, typeof(val)) - print(io, " = ") - show(io, mime, val) - end + show(io, undeftypeof(val)) + print(io, " = ") + show(io, mime, val) print(io, "\n") end end diff --git a/src/macro.jl b/src/macro.jl index 0a08840..3173106 100644 --- a/src/macro.jl +++ b/src/macro.jl @@ -158,9 +158,6 @@ end function deducefieldtypes!(fields::Vector{>:FieldInfo}) namedfields = filter(field -> field.name isa Symbol, fields) for field in fields - if field.type != UndefProperty - continue - end thistype = NamedTuple{tuple(map(field -> field.name, namedfields)...), Tuple{map(field -> field.type, namedfields)...}} fieldconstype = deducetype(field.tfunc, thistype) if fieldconstype !== Union{} @@ -232,7 +229,7 @@ function generateserializemethod(constructname::Symbol, structname::Symbol, fiel push!(sercalls, field.line) end if isnothing(field.name) - fielddata = UndefProperty() + fielddata = UndefProperty{field.type}() else fielddata = Expr(:(.), this, @@ -370,7 +367,7 @@ function generateestimatesizemethod(constructname::Symbol, structname::Symbol, f ), escape_excludes(field.cons, [this]) ) - # if the construct can't accept UndefProperty() while the code has it, + # if the construct can't accept UndefProperty{T}() while the code has it, # the size is just UnboundedSize(0) (like any other unknown sized construct) szcall = Expr(:try, Expr(:block, szcall), diff --git a/test/runtests.jl b/test/runtests.jl index 2598a09..033bac9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -84,7 +84,7 @@ end @test repr(UndefProperty()) == "#undef" @test_throws ArgumentError Container(1) @test Container(im).im - @test Container{Complex{Bool}}().im == UndefProperty() + @test Container{Complex{Bool}}().im == UndefProperty{Bool}() @test_throws ErrorException Container{Complex{Bool}}().i @test_throws ErrorException Container(im).im = false @test propertynames(Container(1//2)) == propertynames(1//2) @@ -98,8 +98,8 @@ end """ @test repr("text/plain", Container{Complex{Int64}}()) == """ Container{Complex{Int64}}: - re: #undef - im: #undef + re: Int64 = #undef + im: Int64 = #undef """ end @testset "primitive io" begin @@ -377,6 +377,11 @@ end @test_throws ValidationError serialize(Const(0x0102), 0x0201) end @testset "Overwrite" begin + @testset "deduce type" begin + @test Constructs.deducetype((v) -> Overwrite(UInt8, v), UInt8) <: Construct{UInt8} + @test Constructs.deducetype((v) -> Overwrite(UInt8, v), Function) <: Construct{UInt8} + @test Constructs.deducetype((v) -> Overwrite(UInt8, v), UndefProperty) <: Construct{UInt8} + end @test_throws ArgumentError Overwrite(UInt8, () -> 0x01) @test serialize(Overwrite(UInt8, 0x01), 2) == b"\x01" @test serialize(Overwrite(UInt8, 0x02), UndefProperty()) == b"\x02"