From f8a9dd39d96e7e7245560b2a69aadb6f4e902aa6 Mon Sep 17 00:00:00 2001 From: JonasIsensee Date: Thu, 4 Jan 2024 18:07:39 +0100 Subject: [PATCH] some cleanup (#526) * some cleanup * use wrapped pconvert -> convert to avoid invalidation --- src/JLD2.jl | 3 + src/Lookup3.jl | 14 +- src/data/custom_serialization.jl | 1 + src/data/number_types.jl | 2 +- src/data/reconstructing_datatypes.jl | 4 +- src/data/specialcased_types.jl | 12 +- src/data/type_defs.jl | 2 +- src/data/writing_datatypes.jl | 52 +++-- src/dataio.jl | 2 +- src/misc.jl | 4 +- src/mmapio.jl | 4 +- test/recon.jl | 317 --------------------------- test/recon_funcs.jl | 39 ---- 13 files changed, 51 insertions(+), 405 deletions(-) delete mode 100644 test/recon.jl delete mode 100644 test/recon_funcs.jl diff --git a/src/JLD2.jl b/src/JLD2.jl index a8417e36..f0abfe8b 100644 --- a/src/JLD2.jl +++ b/src/JLD2.jl @@ -44,6 +44,9 @@ jlwrite(io, x) = Base.write(io, x) jlread(io, x) = Base.read(io, x) jlread(io::IO, ::Type{T}, n::Integer) where {T} = T[jlread(io, T) for _=1:n] +# Use internal convert function (for pointer conversion) to avoid invalidations +pconvert(T, x) = Base.convert(T, x) + jlsizeof(x) = Base.sizeof(x) jlunsafe_store!(p, x) = Base.unsafe_store!(p, x) jlunsafe_load(p) = Base.unsafe_load(p) diff --git a/src/Lookup3.jl b/src/Lookup3.jl index f9b06bd4..ae880eea 100644 --- a/src/Lookup3.jl +++ b/src/Lookup3.jl @@ -1,5 +1,5 @@ module Lookup3 -import JLD2: jlunsafe_load +import JLD2: jlunsafe_load, pconvert # Original source at http://www.burtleburtle.net/bob/c/lookup3.c @@ -147,11 +147,11 @@ function hash(k::Ptr{UInt8}, n::Integer=length(k), initval::UInt32=UInt32(0)) # offset += 12 # end @inbounds while n > 12 - a += jlunsafe_load(convert(Ptr{UInt32}, ptr)) + a += jlunsafe_load(pconvert(Ptr{UInt32}, ptr)) ptr += 4 - b += jlunsafe_load(convert(Ptr{UInt32}, ptr)) + b += jlunsafe_load(pconvert(Ptr{UInt32}, ptr)) ptr += 4 - c += jlunsafe_load(convert(Ptr{UInt32}, ptr)) + c += jlunsafe_load(pconvert(Ptr{UInt32}, ptr)) (a, b, c) = mix(a, b, c) ptr += 4 n -= 12 @@ -175,7 +175,7 @@ function hash(k::Ptr{UInt8}, n::Integer=length(k), initval::UInt32=UInt32(0)) # end @inbounds if n > 0 if n == 12 - c += jlunsafe_load(convert(Ptr{UInt32}, ptr+8)) + c += jlunsafe_load(pconvert(Ptr{UInt32}, ptr+8)) @goto n8 elseif n == 11 c += UInt32(jlunsafe_load(Ptr{UInt8}(ptr+10)))<<16 @@ -190,7 +190,7 @@ function hash(k::Ptr{UInt8}, n::Integer=length(k), initval::UInt32=UInt32(0)) @goto n8 elseif n == 8 @label n8 - b += jlunsafe_load(convert(Ptr{UInt32}, ptr+4)) + b += jlunsafe_load(pconvert(Ptr{UInt32}, ptr+4)) @goto n4 elseif n == 7 @label n7 @@ -206,7 +206,7 @@ function hash(k::Ptr{UInt8}, n::Integer=length(k), initval::UInt32=UInt32(0)) @goto n4 elseif n == 4 @label n4 - a += jlunsafe_load(convert(Ptr{UInt32}, ptr)) + a += jlunsafe_load(pconvert(Ptr{UInt32}, ptr)) elseif n == 3 @label n3 a += UInt32(jlunsafe_load(Ptr{UInt8}(ptr+2)))<<16 diff --git a/src/data/custom_serialization.jl b/src/data/custom_serialization.jl index 77acfe2e..6bb10dd2 100644 --- a/src/data/custom_serialization.jl +++ b/src/data/custom_serialization.jl @@ -7,6 +7,7 @@ writeas(T::Type) = T # respectively. These fall back to convert. wconvert(T, x) = convert(T, x) rconvert(T, x) = convert(T, x) +rconvert(::Type{Array{T,N}}, x::Array{T2,N}) where {T, T2, N} = T[rconvert(T, y) for y in x] # Select an ODR, incorporating custom serialization only if the types do not # match diff --git a/src/data/number_types.jl b/src/data/number_types.jl index 615fa1b8..af176bb3 100644 --- a/src/data/number_types.jl +++ b/src/data/number_types.jl @@ -23,7 +23,7 @@ struct BENumber{T} end jlconvert(::ReadRepresentation{T,BENumber{T}}, ::JLDFile, ptr::Ptr, ::RelOffset) where {T} = - bswap(jlunsafe_load(convert(Ptr{T}, ptr))) + bswap(jlunsafe_load(pconvert(Ptr{T}, ptr))) function jltype(f::JLDFile, dt::FixedPointDatatype) signed = Bool(dt.bitfield1 >> 3 & 0b1) diff --git a/src/data/reconstructing_datatypes.jl b/src/data/reconstructing_datatypes.jl index 1375c140..1ca55e92 100644 --- a/src/data/reconstructing_datatypes.jl +++ b/src/data/reconstructing_datatypes.jl @@ -359,7 +359,7 @@ end function types_from_refs(f::JLDFile, ptr::Ptr) # Test for a potential null pointer indicating an empty array - isinit = jlunsafe_load(convert(Ptr{UInt32}, ptr)) != 0 + isinit = jlunsafe_load(pconvert(Ptr{UInt32}, ptr)) != 0 unknown_params = false if isinit refs = jlconvert(ReadRepresentation{RelOffset, Vlen{RelOffset}}(), f, ptr, NULL_REFERENCE) @@ -684,7 +684,7 @@ end # This jlconvert method handles compound types with padding or references @generated function jlconvert(::ReadRepresentation{T,S}, f::JLDFile, ptr::Ptr, header_offset::RelOffset) where {T,S} - isa(S, DataType) && return :(convert(T, jlunsafe_load(convert(Ptr{S}, ptr)))) + isa(S, DataType) && return :(convert(T, jlunsafe_load(pconvert(Ptr{S}, ptr)))) @assert isa(S, OnDiskRepresentation) offsets = typeof(S).parameters[1] diff --git a/src/data/specialcased_types.jl b/src/data/specialcased_types.jl index e00ef43a..ab965204 100644 --- a/src/data/specialcased_types.jl +++ b/src/data/specialcased_types.jl @@ -6,7 +6,7 @@ end function jlconvert(rr::ReadRepresentation{OpaqueData{N}, NTuple{N,UInt8}}, ::JLDFile, ptr::Ptr, ::RelOffset) where N data = Vector{UInt8}(undef, N) - unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), N) + unsafe_copyto!(pointer(data), pconvert(Ptr{UInt8}, ptr), N) OpaqueData(data) end @@ -106,7 +106,7 @@ jlconvert(::ReadRepresentation{Vector{T},Vlen{ODR}}, f::JLDFile, ptr::Ptr, ::Rel function h5convert!(out::Pointers, fls::FixedLengthString, f::JLDFile, x, ::JLDWriteSession) fls.length == jlsizeof(x) || throw(InvalidDataException()) - (unsafe_copyto!(convert(Ptr{UInt8}, out), pointer(x), fls.length); nothing) + (unsafe_copyto!(pconvert(Ptr{UInt8}, out), pointer(x), fls.length); nothing) end h5convert!(out::Pointers, ::Type{Vlen{String}}, f::JLDFile, x, wsession::JLDWriteSession) = store_vlen!(out, UInt8, f, unsafe_wrap(Vector{UInt8}, x), wsession) @@ -115,25 +115,25 @@ jlconvert(::ReadRepresentation{String,Vlen{String}}, f::JLDFile, ptr::Ptr, ::Rel String(jlconvert(ReadRepresentation{UInt8,Vlen{UInt8}}(), f, ptr, NULL_REFERENCE)) function jlconvert(rr::FixedLengthString{String}, ::JLDFile, ptr::Ptr, ::RelOffset) data = Vector{UInt8}(undef, rr.length) - unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), rr.length) + unsafe_copyto!(pointer(data), pconvert(Ptr{UInt8}, ptr), rr.length) String(data) end # Ascii String function jlconvert(rr::AsciiString{NullTerminated}, ::JLDFile, ptr::Ptr, ::RelOffset) data = Vector{UInt8}(undef, rr.length) - unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), rr.length) + unsafe_copyto!(pointer(data), pconvert(Ptr{UInt8}, ptr), rr.length) String(data[1:end-1]) end function jlconvert(rr::ReadRepresentation{String, FixedLengthAsciiString{NullTerminated,N}}, ::JLDFile, ptr::Ptr, ::RelOffset) where {N} data = Vector{UInt8}(undef, N) - unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), N) + unsafe_copyto!(pointer(data), pconvert(Ptr{UInt8}, ptr), N) String(data) end function jlconvert(rr::ReadRepresentation{String, FixedLengthAsciiString{SpacePadded,N}}, ::JLDFile, ptr::Ptr, ::RelOffset) where {N} data = Vector{UInt8}(undef, N) - unsafe_copyto!(pointer(data), convert(Ptr{UInt8}, ptr), N) + unsafe_copyto!(pointer(data), pconvert(Ptr{UInt8}, ptr), N) rstrip(String(data)) end odr_sizeof(x::AsciiString) = x.length diff --git a/src/data/type_defs.jl b/src/data/type_defs.jl index 26ddb1d5..b57c6e30 100644 --- a/src/data/type_defs.jl +++ b/src/data/type_defs.jl @@ -9,7 +9,7 @@ odr_sizeof(::Nothing) = 0 function datatype_size(dt::DataType) Base.@_foldable_meta dt.layout == C_NULL && throw(UndefRefError()) - size = unsafe_load(convert(Ptr{Base.DataTypeLayout}, dt.layout)).size + size = unsafe_load(pconvert(Ptr{Base.DataTypeLayout}, dt.layout)).size return Int(size) end @Base.pure odr_sizeof(x::DataType) = datatype_size(x) diff --git a/src/data/writing_datatypes.jl b/src/data/writing_datatypes.jl index 8b587912..8f39e56e 100644 --- a/src/data/writing_datatypes.jl +++ b/src/data/writing_datatypes.jl @@ -71,16 +71,16 @@ const MAX_INLINE_SIZE = 2^10 # fieldodr gives the on-disk representation of a field of a given type, # which is either always initialized (initialized=true) or potentially # uninitialized (initialized=false) -@generated function fieldodr(::Type{T}, initialized::Bool) where T +function fieldodr(::Type{T}, initialized::Bool) where T if isconcretetype(T) if !hasfielddata(T) # A ghost type, so no need to store at all return nothing elseif isa(T, DataType) && sizeof(T) ≤ MAX_INLINE_SIZE if isbitstype(T) - return :(odr(T)) + return odr(T) elseif !ismutabletype(T) - return :(initialized ? odr(T) : RelOffset) + return initialized ? odr(T) : RelOffset end end end @@ -89,21 +89,19 @@ end # h5fieldtype is fieldodr's HDF5 companion. It should give the HDF5 # datatype reflecting the on-disk representation. -@generated function h5fieldtype(f::JLDFile, writeas::Type{T}, readas::Type, +function h5fieldtype(f::JLDFile, writeas::Type{T}, readas::Type, initialized::Initialized) where T if isconcretetype(T) if !hasfielddata(T) return nothing - elseif (isbitstype(T) || (isa(initialized, Type{Type{Val{true}}}) && !ismutabletype(T))) && sizeof(T) ≤ MAX_INLINE_SIZE - return quote - @lookup_committed f T - $(if isempty(T.types) - # Opaque datatype - :(return commit(f, OpaqueDatatype(sizeof(T)), T, readas)) - else - # Compound type - :(return commit_compound(f, fieldnames(T), T, readas)) - end) + elseif (isbitstype(T) || (isa(initialized, Type{Val{true}}) && !ismutabletype(T))) && sizeof(T) ≤ MAX_INLINE_SIZE + @lookup_committed f T + if isempty(T.types) + # Opaque datatype + return commit(f, OpaqueDatatype(sizeof(T)), T, readas) + else + # Compound type + return commit_compound(f, fieldnames(T), T, readas) end end end @@ -232,7 +230,7 @@ end # method handles types with no padding or references where this is just a simple # store h5convert!(out::Pointers, ::Type{T}, ::JLDFile, x, ::JLDWriteSession) where {T} = - (jlunsafe_store!(convert(Ptr{T}, out), x); nothing) + (jlunsafe_store!(pconvert(Ptr{T}, out), x); nothing) # We pack types that have padding using a staged h5convert! method @generated function h5convert!(out::Pointers, @@ -276,7 +274,7 @@ jlconvert_canbeuninitialized(::Any) = false # handles types where this is just a simple load @inline jlconvert(::ReadRepresentation{T,T}, ::JLDFile, ptr::Ptr, ::RelOffset) where {T} = - jlunsafe_load(convert(Ptr{T}, ptr)) + jlunsafe_load(pconvert(Ptr{T}, ptr)) # When fields are undefined in the file but can't be in the workspace, we need # to throw exceptions to prevent errors on null pointer loads @@ -297,37 +295,37 @@ odr(::Type{RelOffset}) = RelOffset @inline function h5convert!(out::Pointers, odr::Type{RelOffset}, f::JLDFile, x::Any, wsession::JLDWriteSession) ref = write_ref(f, x, wsession) - jlunsafe_store!(convert(Ptr{RelOffset}, out), ref) + jlunsafe_store!(pconvert(Ptr{RelOffset}, out), ref) nothing end h5convert_uninitialized!(out::Pointers, odr::Type{RelOffset}) = - (jlunsafe_store!(convert(Ptr{RelOffset}, out), NULL_REFERENCE); nothing) + (jlunsafe_store!(pconvert(Ptr{RelOffset}, out), NULL_REFERENCE); nothing) # Reading references as references jlconvert(::ReadRepresentation{RelOffset,RelOffset}, f::JLDFile, ptr::Ptr, ::RelOffset) = - jlunsafe_load(convert(Ptr{RelOffset}, ptr)) + jlunsafe_load(pconvert(Ptr{RelOffset}, ptr)) jlconvert_canbeuninitialized(::ReadRepresentation{RelOffset,RelOffset}) = false # Reading references as other types @inline function jlconvert(::ReadRepresentation{T,RelOffset}, f::JLDFile, ptr::Ptr, ::RelOffset) where T - x = load_dataset(f, jlunsafe_load(convert(Ptr{RelOffset}, ptr))) + x = load_dataset(f, jlunsafe_load(pconvert(Ptr{RelOffset}, ptr))) (isa(x, T) ? x : rconvert(T, x))::T end jlconvert_canbeuninitialized(::ReadRepresentation{T,RelOffset}) where {T} = true jlconvert_isinitialized(::ReadRepresentation{T,RelOffset}, ptr::Ptr) where {T} = - jlunsafe_load(convert(Ptr{RelOffset}, ptr)) != NULL_REFERENCE + jlunsafe_load(pconvert(Ptr{RelOffset}, ptr)) != NULL_REFERENCE ## Routines for variable-length datatypes # Write variable-length data and store the offset and length to out pointer @inline function store_vlen!(out::Pointers, odr, f::JLDFile, x::AbstractVector, wsession::JLDWriteSession) - jlunsafe_store!(convert(Ptr{UInt32}, out), length(x)) + jlunsafe_store!(pconvert(Ptr{UInt32}, out), length(x)) obj = write_heap_object(f, odr, x, wsession) - jlunsafe_store!(convert(Ptr{GlobalHeapID}, out)+4, obj) + jlunsafe_store!(pconvert(Ptr{GlobalHeapID}, out)+4, obj) nothing end @@ -336,14 +334,14 @@ h5convert!(out::Pointers, ::Type{Vlen{T}}, f::JLDFile, x, wsession::JLDWriteSess @assert odr_sizeof(Vlen) == jlsizeof(UInt128) h5convert_uninitialized!(out::Pointers, odr::Type{T}) where {T<:Vlen} = - (jlunsafe_store!(convert(Ptr{Int128}, out), 0); nothing) + (jlunsafe_store!(pconvert(Ptr{Int128}, out), 0); nothing) # Read variable-length data given offset and length in ptr jlconvert(::ReadRepresentation{T,Vlen{S}}, f::JLDFile, ptr::Ptr, ::RelOffset) where {T,S} = - read_heap_object(f, jlunsafe_load(convert(Ptr{GlobalHeapID}, ptr+4)), ReadRepresentation{T, S}()) + read_heap_object(f, jlunsafe_load(pconvert(Ptr{GlobalHeapID}, ptr+4)), ReadRepresentation{T, S}()) jlconvert_canbeuninitialized(::ReadRepresentation{T,Vlen{S}}) where {T,S} = true jlconvert_isinitialized(::ReadRepresentation{T,Vlen{S}}, ptr::Ptr) where {T,S} = - jlunsafe_load(convert(Ptr{GlobalHeapID}, ptr+4)) != GlobalHeapID(RelOffset(0), 0) + jlunsafe_load(pconvert(Ptr{GlobalHeapID}, ptr+4)) != GlobalHeapID(RelOffset(0), 0) @@ -635,7 +633,7 @@ datamode(::DataType) = ReferenceFree() datamode(::FixedLengthString) = ReferenceFree() datamode(::AsciiString) = ReferenceFree() datamode(::Nothing) = ReferenceFree() -@generated function datamode(odr::OnDiskRepresentation{Offsets,JLTypes,H5Types,Size} where {Offsets,JLTypes,Size}) where H5Types +function datamode(odr::OnDiskRepresentation{Offsets,JLTypes,H5Types,Size} where {Offsets,JLTypes,Size}) where H5Types for ty in H5Types.parameters datamode(ty) == HasReferences() && return HasReferences() end diff --git a/src/dataio.jl b/src/dataio.jl index 048ddb29..51787141 100644 --- a/src/dataio.jl +++ b/src/dataio.jl @@ -54,7 +54,7 @@ end seek(regulario, inptr - io.startptr) unsafe_read(regulario, pointer(v), nb) else - unsafe_copyto!(pointer(v), convert(Ptr{T}, inptr), n) + unsafe_copyto!(pointer(v), pconvert(Ptr{T}, inptr), n) end io.curptr = inptr + odr_sizeof(T) * n v diff --git a/src/misc.jl b/src/misc.jl index f606a358..d7bf3668 100644 --- a/src/misc.jl +++ b/src/misc.jl @@ -12,11 +12,11 @@ function define_packed(ty::DataType) if sz != jlsizeof(ty) @eval begin function jlunsafe_store!(p::Ptr{$ty}, x::$ty) - $([:(jlunsafe_store!(convert(Ptr{$(ty.types[i])}, p+$(packed_offsets[i])), getfield(x, $i))) + $([:(jlunsafe_store!(pconvert(Ptr{$(ty.types[i])}, p+$(packed_offsets[i])), getfield(x, $i))) for i = 1:length(packed_offsets)]...) end function jlunsafe_load(p::Ptr{$ty}) - $(Expr(:new, ty, [:(jlunsafe_load(convert(Ptr{$(ty.types[i])}, p+$(packed_offsets[i])))) + $(Expr(:new, ty, [:(jlunsafe_load(pconvert(Ptr{$(ty.types[i])}, p+$(packed_offsets[i])))) for i = 1:length(packed_offsets)]...)) end jlsizeof(::Union{$ty,Type{$ty}}) = $(Int(sz))::Int diff --git a/src/mmapio.jl b/src/mmapio.jl index 5dc27a42..2b711874 100644 --- a/src/mmapio.jl +++ b/src/mmapio.jl @@ -236,7 +236,7 @@ jlread(io::MmapIO, ::Type{T}, n::Integer) where {T} = read(io, T, Int(n)) function read_bytestring(io::MmapIO) # TODO do not try to read outside the buffer cp = io.curptr - str = unsafe_string(convert(Ptr{UInt8}, cp)) + str = unsafe_string(pconvert(Ptr{UInt8}, cp)) io.curptr = cp + jlsizeof(str) + 1 str end @@ -277,7 +277,7 @@ function IndirectPointer(io::MmapIO, offset::Integer=position(io)) IndirectPointer(pointer_from_objref(io) + fieldoffset(MmapIO, 4), offset) end Base.:+(x::IndirectPointer, y::Integer) = IndirectPointer(x.ptr, x.offset+y) -Base.convert(::Type{Ptr{T}}, x::IndirectPointer) where {T} = Ptr{T}(jlunsafe_load(x.ptr) + x.offset) +pconvert(::Type{Ptr{T}}, x::IndirectPointer) where {T} = Ptr{T}(jlunsafe_load(x.ptr) + x.offset) # We sometimes need to compute checksums. We do this by first calling begin_checksum when # starting to handle whatever needs checksumming, and calling end_checksum afterwards. Note diff --git a/test/recon.jl b/test/recon.jl deleted file mode 100644 index a2ac7298..00000000 --- a/test/recon.jl +++ /dev/null @@ -1,317 +0,0 @@ -using JLD2 - -mutable struct TestType1 - x::Int -end -mutable struct TestType2 - x::Int -end -struct TestType3 - x::TestType2 -end - -mutable struct TestType4 - x::Int -end -mutable struct TestType5 - x::TestType4 -end -mutable struct TestType6 end -primitive type TestType7 8 end -struct TestType8 - a::TestType4 - b::TestType5 - c::TestType6 - d::TestType7 -end -struct TestTypeContainer{T} - a::T - b::Int -end -primitive type TestType9 16 end -struct TestType10 - a::Int - b::UInt8 -end -struct TestType11 - a::Int - b::UInt8 -end -struct TestType12 - x::String -end -mutable struct TestType13 - a - TestType13() = new() -end -struct TestType14{T} - x::T - y::Int -end -struct TestType15{T,S} - x::T - y::S -end -struct TestType16{T} - x::T - y::Int -end -struct TestTypeContainer2{T} - a::T - b::Int -end -struct TestTypeContainer3{T,S} - a::T - b::S -end -struct TestTypeContainer4{T} - a::T - b::Int -end -struct TestTypeContainer5{T,S} - a::T - b::S -end -struct TestType17 - x::Int -end -struct TestType18 - x::Int -end -struct TestType19{T} - x::T -end -primitive type TestType20 16 end -struct TestType21 end - - -fn = joinpath(mktempdir(), "test.jld") -file = jldopen(fn, "w") -write(file, "x1", TestType1(57)) -write(file, "x2", TestType3(TestType2(1))) -write(file, "x3", TestType4(1)) -write(file, "x4", TestType5(TestType4(2))) -write(file, "x5", [TestType5(TestType4(i)) for i = 1:5]) -write(file, "x6", TestType6()) -write(file, "x7", reinterpret(TestType7, 0x77)) -write(file, "x8", TestType8(TestType4(2), TestType5(TestType4(3)), - TestType6(), reinterpret(TestType7, 0x12))) -write(file, "x9", (TestType4(1), - (TestType5(TestType4(2)), - [TestType5(TestType4(i)) for i = 1:5]), - TestType6())) -write(file, "x10", TestTypeContainer(TestType4(3), 4)) -write(file, "x11", reinterpret(TestType9, 0x1234)) -write(file, "x12", TestType10(1234, 0x56)) -write(file, "x13", TestType11(78910, 0x11)) -write(file, "x14", TestType12("abcdefg")) -write(file, "x15", TestType13()) -write(file, "x16", TestType14(1.2345, 67)) -write(file, "x17", TestType15(8.91011, 12)) -write(file, "x18", TestType16(12.131415, 1617)) -write(file, "x19", TestTypeContainer2(TestType4(3), 4)) -write(file, "x20", TestTypeContainer3(TestType4(3), 4)) -write(file, "x21", TestTypeContainer4(TestType4(3), 4)) -write(file, "x22", TestTypeContainer5(TestType4(3), 4)) -write(file, "x23", TestType17(5678910)) -write(file, "x24", Dict(TestType4(1) => TestType5(TestType4(2)))) -write(file, "x25", Dict(TestType17(1) => reinterpret(TestType9, 0x4567))) -write(file, "x26", TestType18(1337)) -write(file, "x27", TestType19(31337)) -write(file, "x28", reinterpret(TestType20, 0x1337)) -write(file, "x29", TestType21()) - -close(file) - -workspace() - -# workspace doesn't work anymore unless we call @eval Core.Main afterwards. Unfortunately, we can't -# just put all this code in a block, because then it won't be evaluated at top-level. So -# we need a bunch of @eval Core.Mains here. -@eval Core.Main using .LastMain.JLD2, Compat, Test -@eval Core.Main mutable struct TestType1 - x::Float64 -end -@eval Core.Main mutable struct TestType2 - x::Int -end -@eval Core.Main struct TestType3 - x::TestType1 -end -@eval Core.Main struct TestTypeContainer{T} - a::T - b::Int -end -@eval Core.Main primitive type TestType9 8 end -@eval Core.Main struct TestType10 - a::Int - b::UInt8 - c::UInt8 -end -@eval Core.Main struct TestType11 - b::UInt8 -end -@eval Core.Main struct TestType12 - x::Int -end -@eval Core.Main mutable struct TestType13 - a -end -@eval Core.Main struct TestType14{T,S} - x::T - y::S -end -@eval Core.Main struct TestType15{T} - x::T - y::Float64 -end -@eval Core.Main struct TestType16{T<:Integer} - x::T - y::Int -end -@eval Core.Main struct TestTypeContainer2{T} - a::T - b::String -end -@eval Core.Main struct TestTypeContainer3{T,S} - a::T - b::S -end -@eval Core.Main struct TestTypeContainer4{T,S} - a::T - b::S -end -@eval Core.Main struct TestTypeContainer5{T} - a::T - b::Int -end -@eval Core.Main abstract type TestType18 end -@eval Core.Main struct TestType19 end -@eval Core.Main struct TestType20 - x::UInt16 -end -@eval Core.Main struct TestType21 - x::Int -end -@eval Core.Main begin -const TestType17 = 5 - -file = jldopen(LastMain.fn, "r") -x = read(file, "x1") -@test isa(x, TestType1) -@test x.x === 57.0 -@test_throws MethodError read(file, "x2") -println("The following missing type warnings are a sign of normal operation.") -@test read(file, "x3").x == 1 -@test read(file, "x4").x.x == 2 - -x = read(file, "x5") -for i = 1:5 - @test x[i].x.x == i -end -@test isempty(fieldnames(typeof(read(file, "x6")))) -@test reinterpret(UInt8, read(file, "x7")) == 0x77 - -x = read(file, "x8") -@test x.a.x == 2 -@test x.b.x.x == 3 -@test isempty(fieldnames(typeof(x.c))) -@test reinterpret(UInt8, x.d) == 0x12 - -x = read(file, "x9") -@test isa(x, Tuple) -@test length(x) == 3 -@test x[1].x == 1 -@test isa(x[2], Tuple) -@test length(x[2]) == 2 -@test x[2][1].x.x == 2 -for i = 1:5 - @test x[2][2][i].x.x == i -end -@test isempty(fieldnames(typeof(x[3]))) - -x = read(file, "x10") -@test isa(x, TestTypeContainer{Any}) -@test x.a.x === 3 -@test x.b === 4 - -x = read(file, "x11") -@test !isa(x, TestType9) -@test reinterpret(UInt16, x) === 0x1234 - -x = read(file, "x12") -@test !isa(x, TestType10) -@test x.a === 1234 -@test x.b === 0x56 - -x = read(file, "x13") -@test isa(x, TestType11) -@test x.b === 0x11 - -x = read(file, "x14") -@test !isa(x, TestType12) -@test x.x == "abcdefg" - -@test_throws JLD2.UndefinedFieldException x = read(file, "x15") - -x = read(file, "x16") -@test !isa(x, TestType14) -@test x.x === 1.2345 -@test x.y === 67 - -x = read(file, "x17") -@test !isa(x, TestType15) -@test x.x === 8.91011 -@test x.y === 12 - -x = read(file, "x18") -@test !isa(x, TestType16) -@test x.x === 12.131415 -@test x.y === 1617 - -x = read(file, "x19") -@test !isa(x, TestTypeContainer2) -@test x.a.x === 3 -@test x.b === 4 - -x = read(file, "x20") -@test isa(x, TestTypeContainer3{Any,Int}) -@test x.a.x === 3 -@test x.b === 4 - -x = read(file, "x21") -@test !isa(x, TestTypeContainer4) -@test x.a.x === 3 -@test x.b === 4 - -x = read(file, "x22") -@test !isa(x, TestTypeContainer5) -@test x.a.x === 3 -@test x.b === 4 - -x = read(file, "x23") -@test x.x === 5678910 - -x = read(file, "x24") -@test first(x).first.x === 1 -@test first(x).second.x.x === 2 - -x = read(file, "x25") -@test first(x).first.x === 1 -@test reinterpret(UInt16, first(x).second) === 0x4567 - -x = read(file, "x26") -@test x.x === 1337 - -x = read(file, "x27") -@test x.x === 31337 - -x = read(file, "x28") -@test !isa(x, TestType20) -@test reinterpret(UInt16, x) == 0x1337 - -x = read(file, "x29") -@test sizeof(x) == 0 - -close(file) -end diff --git a/test/recon_funcs.jl b/test/recon_funcs.jl deleted file mode 100644 index d8f14bce..00000000 --- a/test/recon_funcs.jl +++ /dev/null @@ -1,39 +0,0 @@ -using FileIO, JLD2, Test - -struct S1 - a - f -end - -struct S2{F} - a - f::F -end - -struct S3{F} - f::F -end - -λ() = 42 - -function round_trip(x) - mktempdir() do dir - fn = joinpath(dir, "test.jld2") - @save fn grp=x - @load fn grp - return grp - end -end - -@testset "round trip Function values" begin - @test 42 == round_trip(λ)() - @test 42 == first(round_trip((λ,)))() - @test 42 == first(round_trip((λ, λ)))() - @test 42 == first(round_trip((λ, 42)))() - @test 42 == first(round_trip([λ]))() - @test 42 == first(round_trip([λ, λ]))() - @test 42 == first(round_trip([λ, 42]))() - @test 42 == round_trip(S1(42, λ)).f() - @test 42 == round_trip(S2(42, λ)).f() - @test 42 == round_trip(S3(λ)).f() -end