|   |  | 1 |  | """ | 
|   |  | 2 |  |     PointerDict | 
|   |  | 3 |  |  | 
|   |  | 4 |  | `PointerDict` is wrapper around `AbstractDict` that allows to use `JSONPointer` as keys. | 
|   |  | 5 |  |  | 
|   |  | 6 |  | ## Constructors | 
|   |  | 7 |  |  | 
|   |  | 8 |  | PointerDict("a" => 1, "b" => 2) | 
|   |  | 9 |  | PointerDict(j"/a" => 1, j"/b" => 2) | 
|   |  | 10 |  | PointerDict(Dict("a" => 1, "b" => 2) | 
|   |  | 11 |  | """ | 
|   |  | 12 |  | struct PointerDict{K<:Union{String,Symbol}, V} <: AbstractDict{K, V} | 
|   |  | 13 |  |     d::AbstractDict | 
|   |  | 14 |  |  | 
|   | 1 | 15 |  |     PointerDict(@nospecialize pd::PointerDict) = pd | 
|   | 23 | 16 |  |     PointerDict(d::AbstractDict{String,V}) where {V} = new{String,V}(d) | 
|   | 1 | 17 |  |     PointerDict(d::AbstractDict{Symbol,V}) where {V} = new{Symbol,V}(d) | 
|   |  | 18 |  |  | 
|   |  | 19 |  |     function PointerDict(d::T) where T <: AbstractDict | 
|   | 1 | 20 |  |         dict = dicttype(T){String,valtype(d)}() | 
|   | 2 | 21 |  |         for (k,v) in d | 
|   | 3 | 22 |  |             dict[string(k)] = v | 
|   |  | 23 |  |         end | 
|   | 1 | 24 |  |         PointerDict(dict) | 
|   |  | 25 |  |     end | 
|   |  | 26 |  |     function PointerDict(args...) | 
|   | 14 | 27 |  |         d = OrderedDict{String, Any}() | 
|   | 14 | 28 |  |         for (k, v) in args | 
|   | 38 | 29 |  |             if isa(k, Pointer) | 
|   | 31 | 30 |  |                 _setindex!(d, v, k) | 
|   |  | 31 |  |             else | 
|   | 51 | 32 |  |                 setindex!(d, v, k) | 
|   |  | 33 |  |             end | 
|   |  | 34 |  |         end | 
|   | 14 | 35 |  |         PointerDict(d) | 
|   |  | 36 |  |     end | 
|   |  | 37 |  |     # PointerDict(; kwargs...) = PointerDict(values(kwargs)) | 
|   |  | 38 |  | end | 
|   |  | 39 |  |  | 
|   | 1 | 40 |  | dicttype(::Type{T}) where T <: AbstractDict = eval(T.name.wrapper) | 
|   | 1 | 41 |  | dicttype(x::T) where T <: AbstractDict = eval(T.name.wrapper) | 
|   |  | 42 |  |  | 
|   | 0 | 43 |  | Base.IteratorSize(@nospecialize T::Type{<:PointerDict}) = Base.IteratorSize(fieldtype(T, :d)) | 
|   | 0 | 44 |  | Base.IteratorEltype(@nospecialize T::Type{<:PointerDict}) = Base.IteratorEltype(eltype(T)) | 
|   |  | 45 |  |  | 
|   | 1 | 46 |  | Base.keytype(@nospecialize T::Type{<:PointerDict{String}}) = String | 
|   | 0 | 47 |  | Base.keytype(@nospecialize T::Type{<:PointerDict{Symbol}}) = Symbol | 
|   |  | 48 |  |  | 
|   |  | 49 |  | function Base.empty(pd::PointerDict, ::Type{K}=keytype(pd), ::Type{V}=valtype(pd)) where {K,V} | 
|   | 2 | 50 |  |     PointerDict(empty(getfield(pd, :d), K, V)) | 
|   |  | 51 |  | end | 
|   |  | 52 |  |  | 
|   |  | 53 |  | # Simply delegated dictionary functions to the wrapped PointerDdicct object | 
|   |  | 54 |  | # NOTE: push! is not included below, because the fallback version just | 
|   |  | 55 |  | #       calls setindex! | 
|   |  | 56 |  | @delegate_onefield(PointerDict, d, [ Base.getindex, Base.get, Base.get!, Base.haskey, | 
|   |  | 57 |  | Base.getkey, Base.pop!, Base.iterate, | 
|   |  | 58 |  | Base.isempty, Base.length, Base.delete!, Base.setindex!]) | 
|   |  | 59 |  | # Base.copy(pd::PointerDict) = PointerDict(copy(getfield(pd, :d))) | 
|   |  | 60 |  |  | 
|   |  | 61 |  | # empty! returns the wrapped dictionary if simply delegated | 
|   |  | 62 |  | function Base.empty!(pd::PointerDict) | 
|   | 1 | 63 |  |     empty!(getfield(pd, :d)) | 
|   | 1 | 64 |  |     return pd | 
|   |  | 65 |  | end | 
|   |  | 66 |  |  | 
|   |  | 67 |  |  | 
|   |  | 68 |  | function Base.get(pd::PointerDict, jk::Pointer, d) | 
|   | 3 | 69 |  |     _get(getfield(pd, :d), jk, d) | 
|   |  | 70 |  | end | 
|   | 0 | 71 |  | function Base.get(f::Base.Callable, pd::PointerDict, jp::Pointer) | 
|   | 0 | 72 |  |     _get(f, getfield(pd, :d), jp) | 
|   |  | 73 |  | end | 
|   |  | 74 |  |  | 
|   |  | 75 |  | function Base.get!(pd::PointerDict, jp::Pointer, d) | 
|   | 3 | 76 |  |     _get!(getfield(pd, :d), jp, d) | 
|   |  | 77 |  | end | 
|   | 0 | 78 |  | function Base.get!(f::Base.Callable, pd::PointerDict, jp::Pointer) | 
|   | 0 | 79 |  |     _get!(f, getfield(pd, :d), jp) | 
|   |  | 80 |  | end | 
|   |  | 81 |  |  | 
|   |  | 82 |  | function Base.getindex(pd::PointerDict, jp::Pointer) | 
|   | 56 | 83 |  |     _getindex(getfield(pd, :d), jp) | 
|   |  | 84 |  | end | 
|   |  | 85 |  |  | 
|   |  | 86 |  | function Base.setindex!(pd::PointerDict, v, jp::Pointer) | 
|   | 8 | 87 |  |     _setindex!(getfield(pd, :d), v, jp) | 
|   |  | 88 |  | end | 
|   | 20 | 89 |  | Base.haskey(pd::PointerDict, jp::Pointer) = _haskey(getfield(pd, :d), jp) | 
|   | 0 | 90 |  | Base.getkey(pd::PointerDict, jp::Pointer, d) = getkey(getfield(pd, :d), jp, d) | 
|   |  | 91 |  |  | 
|   |  | 92 |  | ## merge and mergewith | 
|   | 0 | 93 |  | Base.merge(pd::PointerDict) = copy(pd) | 
|   |  | 94 |  |  | 
|   |  | 95 |  | function Base.merge(pd::PointerDict, pds::PointerDict...) | 
|   | 2 | 96 |  |     K = _promote_keytypes((pd, pds...)) | 
|   | 2 | 97 |  |     V = _promote_valtypes(valtype(pd), pds...) | 
|   | 2 | 98 |  |     out = PointerDict(Dict{K,V}()) | 
|   | 2 | 99 |  |     for (k,v) in pd | 
|   | 6 | 100 |  |         out[k] = v | 
|   |  | 101 |  |     end | 
|   | 2 | 102 |  |     merge!(recursive_merge, out, pds...) | 
|   |  | 103 |  | end | 
|   |  | 104 |  |  | 
|   | 3 | 105 |  | recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...) | 
|   | 2 | 106 |  | recursive_merge(x::AbstractVector...) = cat(x...; dims=1) | 
|   | 0 | 107 |  | recursive_merge(x...) = x[end] | 
|   |  | 108 |  |  | 
|   |  | 109 |  | # fall back to String if we don't clearly have Symbol | 
|   | 0 | 110 |  | _promote_keytypes(@nospecialize(pds::Tuple{Vararg{PointerDict{Symbol, T}}})) where T = Symbol | 
|   | 2 | 111 |  | _promote_keytypes(@nospecialize(pds::Tuple{Vararg{PointerDict}})) = String | 
|   | 0 | 112 |  | _promote_valtypes(V) = V | 
|   |  | 113 |  | function _promote_valtypes(V, d, ds...)  # give up if promoted to any | 
|   | 2 | 114 |  |     V === Any ? Any : _promote_valtypes(promote_type(V, valtype(d)), ds...) | 
|   |  | 115 |  | end |