diff --git a/Project.toml b/Project.toml index abd5b73..d7bd621 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,6 @@ authors = ["김용희 "] version = "0.4.0" [deps] -Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" [compat] diff --git a/src/JSONPointer.jl b/src/JSONPointer.jl index 7abc627..ce4fd7f 100644 --- a/src/JSONPointer.jl +++ b/src/JSONPointer.jl @@ -1,6 +1,5 @@ module JSONPointer -using Compat using OrderedCollections include("pointer.jl") diff --git a/src/pointer.jl b/src/pointer.jl index c79afd5..1e65d06 100644 --- a/src/pointer.jl +++ b/src/pointer.jl @@ -130,9 +130,7 @@ end function Base.show(io::IO, ::Pointer{Nothing}) print(io, "JSONPointer{Nothing}(\"\")") end -function Base.getindex(A::T, p::Pointer) where T<:AbstractDict - error("test") -end + Base.getindex(A::AbstractArray, p::Pointer) = _getindex(A, p) Base.haskey(A::AbstractArray, p::Pointer) = _haskey(A, p) diff --git a/src/pointerdict.jl b/src/pointerdict.jl index 483d8e1..f259086 100644 --- a/src/pointerdict.jl +++ b/src/pointerdict.jl @@ -17,7 +17,7 @@ struct PointerDict{K<:Union{String,Symbol}, V} <: AbstractDict{K, V} PointerDict(d::AbstractDict{Symbol,V}) where {V} = new{Symbol,V}(d) function PointerDict(d::T) where T <: AbstractDict - dict = T{String,valtype(d)}() + dict = dicttype(T){String,valtype(d)}() for (k,v) in d dict[string(k)] = v end @@ -34,9 +34,12 @@ struct PointerDict{K<:Union{String,Symbol}, V} <: AbstractDict{K, V} end PointerDict(d) end - PointerDict(; kwargs...) = PointerDict(values(kwargs)) + # PointerDict(; kwargs...) = PointerDict(values(kwargs)) end +dicttype(::Type{T}) where T <: AbstractDict = eval(T.name.wrapper) +dicttype(x::T) where T <: AbstractDict = eval(T.name.wrapper) + Base.IteratorSize(@nospecialize T::Type{<:PointerDict}) = Base.IteratorSize(fieldtype(T, :d)) Base.IteratorEltype(@nospecialize T::Type{<:PointerDict}) = Base.IteratorEltype(eltype(T)) @@ -105,8 +108,6 @@ function Base.setindex!(pd::PointerDict, v, jp::Pointer) _setindex!(getfield(pd, :d), v, jp) end -Base.reverse(pd::PointerDict) = PointerDict(reverse(getfield(pd, :d))) - Base.iterate(pd::PointerDict) = iterate(getfield(pd, :d)) Base.iterate(pd::PointerDict, i) = iterate(getfield(pd, :d), i) @@ -130,23 +131,13 @@ function Base.merge(pd::PointerDict, pds::PointerDict...) for (k,v) in pd out[k] = v end - merge!(out, pds...) -end - -@static if VERSION >= v"1.5" - Base.mergewith(combine, pd::PointerDict) = copy(pd) - function Base.mergewith(combine, pd::PointerDict, pds::PointerDict...) - K = _promote_keytypes((pd, pds...)) - V0 = _promote_valtypes(valtype(pd), pds...) - V = promote_type(Core.Compiler.return_type(combine, Tuple{V0,V0}), V0) - out = PointerDict(Dict{K,V}()) - for (k,v) in pd - out[k] = v - end - mergewith!(combine, out, pds...) - end + merge!(recursive_merge, out, pds...) end +recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...) +recursive_merge(x::AbstractVector...) = cat(x...; dims=1) +recursive_merge(x...) = x[end] + # fall back to String if we don't clearly have Symbol _promote_keytypes(@nospecialize(pds::Tuple{Vararg{PointerDict{Symbol, T}}})) where T = Symbol _promote_keytypes(@nospecialize(pds::Tuple{Vararg{PointerDict}})) = String diff --git a/test/runtests.jl b/test/runtests.jl index 78e4403..a645377 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -121,7 +121,7 @@ end @test data[p2] == "Is my Data" end -@testset "access deep nested object" begin +@testset "test for 'getindex', 'get', 'get!'" begin data = [PointerDict("a" => 10)] @test data[j"/1/a"] == 10 @@ -156,6 +156,24 @@ end # get isn't defined for array @test_broken get(data, j"/1", missing) |> ismissing + + data = PointerDict() + @test "this" == get!(data, j"/a", "this") + @test data[j"/a"] == data["a"] == "this" + + @test [1,2,3] == get!(data, j"/b", Any[1,2,3]) + @test data[j"/b"] == data["b"] == [1,2,3] + @test data[j"/b/1"] == data["b"][1] == 1 + @test data[j"/b/2"] == data["b"][2] == 2 + + @test get!(data, j"/b/5", missing) |> ismissing + @test data[j"/b/5"] === data["b"][5] + + @test "that" == get(data, "c", "that") + @test haskey(data, "c") == false + @test "that" == get!(data, "c", "that") + @test haskey(data, "c") + data["e"] = [1] end @testset "literal string for a Number" begin @@ -233,6 +251,56 @@ end end +@testset "PointerDicts" begin + d = Dict("foo"=>1, "bar"=>2) + _keys = collect(keys(d)) + pd = PointerDict(d) + + @test length(pd) == length(d) + + @test empty!(PointerDict(Dict("foo"=>1, :bar=>2))) isa PointerDict + @test empty(pd) == PointerDict(empty(d)) + + @test haskey(pd, "foo") + @test getkey(pd, "buz", nothing) === nothing + + @testset "convert" begin + expected = OrderedDict + result = convert(expected, pd) + + @test result isa expected + end + + @testset "iterate" begin + @test iterate(pd) == iterate(d) + @test iterate(pd, 1) == iterate(d, 1) + @test iterate(pd, 2) == iterate(d, 2) + end + + @testset "iteratorsize" begin + @test Base.IteratorSize(pd) == Base.IteratorSize(d) + end + + @testset "iteratoreltype" begin + @test Base.IteratorEltype(pd) == Base.IteratorEltype(d) + end + + push!(pd, "buz" => 10) + @test pop!(pd, "buz") == 10 + @test pop!(pd, "buz", 20) == 20 + @test sizehint!(pd, 5) === pd + @test get(pd, delete!(pd, "foo"), 10) == 10 + + @testset "merge & mergewith" begin + a = PointerDict(j"/dict/a"=>1, j"/array/1"=>2, "c"=>3) + b = PointerDict(j"/dict/b"=>4, j"/array/1"=>5) + c = PointerDict(j"/dict/dict"=>Dict("aa"=>100), "d"=>nothing) + + @test @inferred(merge(a, b)) == PointerDict(j"/dict/a" => 1, "c"=>3, j"/dict/b" => 4, j"/array"=>Any[2, 5]) + @test @inferred(merge(a, b, c)) == PointerDict(j"/dict/a" => 1, "c"=>3, j"/dict/b" => 4, j"/array"=>Any[2, 5], j"/dict/dict" => Dict("aa" => 100), "d" => nothing) + end +end + @testset "Miscellaneous" begin p1 = j"/a/b/1/c"