diff --git a/docs/src/reference.md b/docs/src/reference.md index 9d04748..700954b 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -37,6 +37,7 @@ subcon ```@docs Adapter{TSub, T} +Adapter(subcon::Union{Type, Construct}, type::Type) SymmetricAdapter{T} SymmetricAdapter(subcon::Union{Type, Construct}, encode::Function) encode diff --git a/src/functional.jl b/src/functional.jl index f786dc8..0795663 100644 --- a/src/functional.jl +++ b/src/functional.jl @@ -71,6 +71,29 @@ function encode(cons::FunctionSymmetricAdapter{T, TSubCon}, obj::T; contextkw... convert(T, apply_optional_contextkw(cons.encode, obj, contextkw)) end +struct TypeAdapter{T, U, TSubCon<:Construct{T}} <: Adapter{T, U} + subcon::TSubCon +end + +TypeAdapter(subcon::TSubCon, ::Type{U}) where {T, U, TSubCon<:Construct{T}} = TypeAdapter{T, U, TSubCon}(subcon) +TypeAdapter(::Type{T}, ::Type{U}) where {T, U} = TypeAdapter(Construct(T), U) + +""" + Adapter(T|subcon, U) -> Adapter{T, U} + +Create a adapter for type `U`. + +# Arguments + +- `T`: the underlying data type. +- `subcon::Construct{T}`: the underlying construct. +- `U`: the object type. +""" +Adapter(subcon::Union{Type, Construct}, type::Type) = TypeAdapter(subcon, type) + +encode(::TypeAdapter{T, U, TSubCon}, obj::U; contextkw...) where {T, U, TSubCon} = convert(T, obj) +decode(::TypeAdapter{T, U, TSubCon}, obj::T; contextkw...) where {T, U, TSubCon} = convert(U, obj) + # internal template struct Prefixed{S, T, TSizeCon<:Construct{S}, TSubCon<:Construct{T}} <: Construct{T} sizecon::TSizeCon diff --git a/test/runtests.jl b/test/runtests.jl index 9d5dcd5..e00d0f0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -164,6 +164,13 @@ end @test_throws ValidationError deserialize(Validator(Int8, (v; kw...) -> v >= get(kw, :min_value, 0)), b"\xfe") @test_throws ValidationError deserialize(Validator(Int8, (v; kw...) -> v >= get(kw, :min_value, 0)), b"\x00"; min_value=1) end + @testset "type Adapter" begin + @test estimatesize(Adapter(UInt8, Int)) == sizeof(UInt8) + @test serialize(Adapter(UInt8, Int), 10) == b"\x0a" + @test_throws InexactError serialize(Adapter(UInt8, Int), 256) + @test deserialize(Adapter(UInt8, Int), b"\x0f") == 15 + @test_throws InexactError deserialize(Adapter(UInt16le, Int8), b"\xff\xff") + end @testset "SymmetricAdapter" begin @test_throws ArgumentError Adapter(UInt8, () -> 0x01) @test SymmetricAdapter(UInt8, ~) == Adapter(UInt8, ~)