Skip to content

Commit 0aa59a0

Browse files
JeffBezansonKeno
authored andcommitted
fix #33466, serialization of IdDict (#33473)
Can still read old data, but new files will not be readable by older versions.
1 parent cff873b commit 0aa59a0

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

stdlib/Serialization/src/Serialization.jl

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Serializer(io::IO) = Serializer{typeof(io)}(io)
3131

3232
const n_int_literals = 33
3333
const n_reserved_slots = 24
34-
const n_reserved_tags = 12
34+
const n_reserved_tags = 11
3535

3636
const TAGS = Any[
3737
Symbol, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128,
@@ -56,6 +56,7 @@ const TAGS = Any[
5656
Symbol, # REF_OBJECT_TAG
5757
Symbol, # FULL_GLOBALREF_TAG
5858
Symbol, # HEADER_TAG
59+
Symbol, # IDDICT_TAG
5960
fill(Symbol, n_reserved_tags)...,
6061

6162
(), Bool, Any, Bottom, Core.TypeofBottom, Type, svec(), Tuple{}, false, true, nothing,
@@ -75,7 +76,7 @@ const TAGS = Any[
7576

7677
@assert length(TAGS) == 255
7778

78-
const ser_version = 8 # do not make changes without bumping the version #!
79+
const ser_version = 9 # do not make changes without bumping the version #!
7980

8081
const NTAGS = length(TAGS)
8182

@@ -133,6 +134,7 @@ const OBJECT_TAG = Int32(o0+12)
133134
const REF_OBJECT_TAG = Int32(o0+13)
134135
const FULL_GLOBALREF_TAG = Int32(o0+14)
135136
const HEADER_TAG = Int32(o0+15)
137+
const IDDICT_TAG = Int32(o0+16)
136138

137139
writetag(s::IO, tag) = (write(s, UInt8(tag)); nothing)
138140

@@ -327,15 +329,26 @@ function serialize(s::AbstractSerializer, ex::Expr)
327329
end
328330
end
329331

330-
function serialize(s::AbstractSerializer, d::Dict)
331-
serialize_cycle_header(s, d) && return
332+
function serialize_dict_data(s::AbstractSerializer, d::AbstractDict)
332333
write(s.io, Int32(length(d)))
333334
for (k,v) in d
334335
serialize(s, k)
335336
serialize(s, v)
336337
end
337338
end
338339

340+
function serialize(s::AbstractSerializer, d::Dict)
341+
serialize_cycle_header(s, d) && return
342+
serialize_dict_data(s, d)
343+
end
344+
345+
function serialize(s::AbstractSerializer, d::IdDict)
346+
serialize_cycle(s, d) && return
347+
writetag(s.io, IDDICT_TAG)
348+
serialize_type_data(s, typeof(d))
349+
serialize_dict_data(s, d)
350+
end
351+
339352
function serialize_mod_names(s::AbstractSerializer, m::Module)
340353
p = parentmodule(m)
341354
if p === m || m === Base
@@ -851,6 +864,11 @@ function handle_deserialize(s::AbstractSerializer, b::Int32)
851864
return read(s.io, Float64)
852865
elseif b == INT8_TAG+13
853866
return read(s.io, Char)
867+
elseif b == IDDICT_TAG
868+
slot = s.counter; s.counter += 1
869+
push!(s.pending_refs, slot)
870+
t = deserialize(s)
871+
return deserialize_dict(s, t)
854872
end
855873
t = desertag(b)::DataType
856874
if t.mutable && length(t.types) > 0 # manual specialization of fieldcount
@@ -1303,7 +1321,7 @@ function deserialize(s::AbstractSerializer, t::DataType)
13031321
end
13041322
end
13051323

1306-
function deserialize(s::AbstractSerializer, T::Type{Dict{K,V}}) where {K,V}
1324+
function deserialize_dict(s::AbstractSerializer, T::Type{<:AbstractDict})
13071325
n = read(s.io, Int32)
13081326
t = T(); sizehint!(t, n)
13091327
deserialize_cycle(s, t)
@@ -1315,6 +1333,10 @@ function deserialize(s::AbstractSerializer, T::Type{Dict{K,V}}) where {K,V}
13151333
return t
13161334
end
13171335

1336+
function deserialize(s::AbstractSerializer, T::Type{Dict{K,V}}) where {K,V}
1337+
return deserialize_dict(s, T)
1338+
end
1339+
13181340
deserialize(s::AbstractSerializer, ::Type{BigInt}) = parse(BigInt, deserialize(s), base = 62)
13191341

13201342
function deserialize(s::AbstractSerializer, t::Type{Regex})

stdlib/Serialization/test/runtests.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,12 @@ let f_data
562562
f = deserialize(IOBuffer(base64decode(f_data)))
563563
@test f(10,3) == 23
564564
end
565+
566+
# issue #33466, IdDict
567+
let d = IdDict([1] => 2, [3] => 4), io = IOBuffer()
568+
serialize(io, d)
569+
seekstart(io)
570+
ds = deserialize(io)
571+
@test Dict(d) == Dict(ds)
572+
@test all([k in keys(ds) for k in keys(ds)])
573+
end

0 commit comments

Comments
 (0)