diff --git a/src/NoBang/singletoncontainers.jl b/src/NoBang/singletoncontainers.jl index f961db92..6b54a180 100644 --- a/src/NoBang/singletoncontainers.jl +++ b/src/NoBang/singletoncontainers.jl @@ -13,16 +13,19 @@ function Base.getindex(v::SingletonVector, i::Integer) end # Define table interface as a `SingletonVector{<:NamedTuple}`: -Tables.istable(::Type{<:SingletonVector{<:NamedTuple{names}}}) where {names} = @isdefined(names) -Tables.rowaccess(::Type{<:SingletonVector{names}}) where {names} = @isdefined(names) -Tables.columnaccess(::Type{<:SingletonVector{names}}) where {names} = @isdefined(names) +Tables.istable(::Type{<:SingletonVector{<:NamedTuple{names}}}) where {names} = + @isdefined(names) +Tables.rowaccess(::Type{<:SingletonVector{<:NamedTuple{names}}}) where {names} = + @isdefined(names) +Tables.columnaccess(::Type{<:SingletonVector{<:NamedTuple{names}}}) where {names} = + @isdefined(names) Tables.rows(x::SingletonVector{<:NamedTuple}) = [x.value] -Tables.columns(x::SingletonVector{<:NamedTuple{names}}) where names = +Tables.columns(x::SingletonVector{<:NamedTuple{names}}) where {names} = NamedTuple{names}(map(x -> [x], Tuple(x.value))) -struct SingletonDict{K, V} <: AbstractDict{K, V} +struct SingletonDict{K,V} <: AbstractDict{K,V} key::K value::V end @@ -30,7 +33,9 @@ end Base.iterate(d::SingletonDict) = (d.key => d.value, nothing) Base.iterate(d::SingletonDict, ::Nothing) = nothing -function Base.getindex(d::SingletonDict{K}, key::K) where K +function Base.getindex(d::SingletonDict{K}, key::K) where {K} @boundscheck d.key == key || throw(BoundsError(d, key)) return d.value end + +Base.length(::SingletonDict) = 1 diff --git a/test/Project.toml b/test/Project.toml index 7c0ebbb9..8da1d1fd 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -12,6 +12,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" diff --git a/test/test_singletoncontainers.jl b/test/test_singletoncontainers.jl new file mode 100644 index 00000000..fff9424d --- /dev/null +++ b/test/test_singletoncontainers.jl @@ -0,0 +1,56 @@ +module TestSingletonContainers + +using BangBang.NoBang: SingletonDict, SingletonVector +using Tables: Tables +using Test + +function test_shows(x) + # smoke tests + @test sprint(show, x) isa String + @test sprint(show, "text/plain", x) isa String + @test string(x) isa String +end + +@testset "SingletonVector" begin + v = SingletonVector(1) + @test v[1] == 1 + @test_throws BoundsError v[2] + @test size(v) == (1,) + @test collect(v)::Vector{Int} == [1] + test_shows(v) +end + +@testset "SingletonVector as a table" begin + @testset for T in [ + SingletonVector, + SingletonVector{Int}, + SingletonVector{<:NamedTuple}, + SingletonVector{NamedTuple}, + ] + @test !Tables.istable(T) + end + + @testset for T in [ + SingletonVector{<:NamedTuple{(:a,)}}, + SingletonVector{<:NamedTuple{(:a,),Tuple{Int}}}, + ] + @test Tables.istable(T) + @test Tables.rowaccess(T) + @test Tables.columnaccess(T) + end + + @testset begin + @test Tables.rows(SingletonVector((a = 1,))) == [(a = 1,)] + @test Tables.columns(SingletonVector((a = 1,))) == (a = [1],) + end +end + +@testset "SingletonDict" begin + d = SingletonDict(:a, 1) + @test d[:a] == 1 + @test_throws BoundsError d[:non_existing_key] + @test collect(d)::Vector{Pair{Symbol,Int}} == [:a => 1] + test_shows(d) +end + +end # module