diff options
author | Claudius Holeksa <mail@keldu.de> | 2023-06-27 12:41:56 +0200 |
---|---|---|
committer | Claudius Holeksa <mail@keldu.de> | 2023-06-27 12:41:56 +0200 |
commit | 5688c721c610e2a8931d6ec6f84dee2d4d65c763 (patch) | |
tree | 3d38ec081061f2d6226a12af93ee092f27882d8c | |
parent | 7668b8aceb42b5a46e1f9ca36d16dbfabe291748 (diff) |
c++,codec,core: Added Union to KelSimple and fixed the native data type.
Made some errors more clear as well
-rw-r--r-- | src/codec/data.h | 14 | ||||
-rw-r--r-- | src/codec/simple.h | 81 | ||||
-rw-r--r-- | src/core/templates.h | 5 | ||||
-rw-r--r-- | tests/codec.cpp | 30 |
4 files changed, 127 insertions, 3 deletions
diff --git a/src/codec/data.h b/src/codec/data.h index 9eb2bfc..397aed1 100644 --- a/src/codec/data.h +++ b/src/codec/data.h @@ -91,12 +91,22 @@ public: SAW_DEFAULT_MOVE(data); template<string_literal lit> + void set(data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native> val){ + value_ = std::move(val); + } + + template<string_literal lit> bool holds_alternative() const { - return std::holds_alternative<parameter_key_pack_index<lit, literals...>::value>(value_); + return (parameter_key_pack_index<lit, literals...>::value == value_.index()); } template<string_literal lit> - data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value>::type, encode::Native>& get(){ + data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get(){ + return std::get<parameter_key_pack_index<lit, literals...>::value>(value_); + } + + template<string_literal lit> + const data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get() const{ return std::get<parameter_key_pack_index<lit, literals...>::value>(value_); } }; diff --git a/src/codec/simple.h b/src/codec/simple.h index 8712c6d..8760754 100644 --- a/src/codec/simple.h +++ b/src/codec/simple.h @@ -82,6 +82,9 @@ struct kelsimple_encode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; { auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<Literal>(), to); + if(eov.is_error()){ + return eov; + } } if constexpr ((i+1) < sizeof...(T)){ auto eov = encode_member<i+1>(from, to); @@ -97,6 +100,41 @@ struct kelsimple_encode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { } }; +template<typename... T, string_literal... Lits, typename FromEnc> +struct kelsimple_encode<schema::Union<schema::Member<T,Lits>...>,FromEnc> { + template<std::size_t i> + static error_or<void> encode_member(const data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + if (from.template holds_alternative<Literal>()) { + { + auto eov = stream_value<schema::UInt64>::encode(static_cast<uint64_t>(i), to); + if(eov.is_error()){ + return eov; + } + } + { + auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<Literal>(), to); + if(eov.is_error()){ + return eov; + } + } + } + + if constexpr ( (i+1) < sizeof...(T) ){ + auto eov = encode_member<i+1>(from, to); + if(eov.is_error()){ + return eov; + } + } + return void_t{}; + } + + static error_or<void> encode(const data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ + return encode_member<0>(from, to); + } +}; + template<typename... T, typename FromEnc> struct kelsimple_encode<schema::Tuple<T...>, FromEnc> { template<std::size_t i> @@ -207,6 +245,9 @@ struct kelsimple_decode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; { auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<Literal>()); + if(eov.is_error()){ + return eov; + } } if constexpr ((i+1) < sizeof...(T)){ auto eov = decode_member<i+1>(from, to); @@ -222,6 +263,46 @@ struct kelsimple_decode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { } }; + +template<typename... T, string_literal... Lits, typename FromEnc> +struct kelsimple_decode<schema::Union<schema::Member<T,Lits>...>,FromEnc> { + template<uint64_t i> + static error_or<void> decode_member(buffer& from, data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& to, uint64_t val){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + + if( i == val ){ + to.template set<Literal>(data<Type, FromEnc>{}); + auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<Literal>()); + if(eov.is_error()){ + return eov; + } + return void_t{}; + } + + if constexpr ((i+1) < sizeof...(T)){ + auto eov = decode_member<i+1>(from, to, val); + if(eov.is_error()){ + return eov; + } + } + return void_t{}; + + } + static error_or<void> decode(buffer& from, data<schema::Union<schema::Member<T,Lits>...>, FromEnc>& to){ + uint64_t val{}; + auto eov = stream_value<schema::UInt64>::decode(val, from); + if(eov.is_error()){ + return eov; + } + if ( val >= sizeof...(T) ){ + return make_error<err::invalid_state>(); + } + return decode_member<0>(from, to, val); + } + +}; + template<typename... T, typename FromEnc> struct kelsimple_decode<schema::Tuple<T...>,FromEnc> { template<std::size_t i> diff --git a/src/core/templates.h b/src/core/templates.h index fcac61b..39befc1 100644 --- a/src/core/templates.h +++ b/src/core/templates.h @@ -16,7 +16,9 @@ struct parameter_pack_index<T, TL0, TL...> { 1u + parameter_pack_index<T, TL...>::value; }; -template <size_t N, class... T> struct parameter_pack_type; +template <size_t N, class... T> struct parameter_pack_type { + static_assert(always_false<T...>, "Should've been caught by the specializations"); +}; template <class TN, class... T> struct parameter_pack_type<0, TN, T...> { using type = TN; @@ -25,6 +27,7 @@ template <class TN, class... T> struct parameter_pack_type<0, TN, T...> { template <size_t N, class TN, class... T> struct parameter_pack_type<N, TN, T...> { static_assert(sizeof...(T) > 0, "Exhausted parameters"); + static_assert(N > 0, "Invalid number. Should've been caught"); using type = typename parameter_pack_type<N - 1, T...>::type; }; /* diff --git a/tests/codec.cpp b/tests/codec.cpp index 442ae57..7253ecc 100644 --- a/tests/codec.cpp +++ b/tests/codec.cpp @@ -18,6 +18,11 @@ using TestStruct = Struct< Member<UInt64, "number"> >; +using TestUnion = Union< + Member<TwoDimArray, "two_dim_array">, + Member<UInt64, "number"> +>; + using TestTuple = Tuple< TwoDimArray, UInt64 @@ -196,6 +201,31 @@ SAW_TEST("KelSimple Struct write and read back"){ SAW_EXPECT(dec_tda.at(0,1).get() == 3, "Incorrect Decoding in array 0,1"); SAW_EXPECT(native.template get<"number">().get() == 410, "Incorrect Decoding in number"); } + +SAW_TEST("KelSimple Union write and read back"){ + using namespace saw; + + data<schema::TestUnion,encode::Native> native; + data<schema::TestUnion,encode::KelSimple> simple; + + native.template set<"number">(data<schema::UInt64, encode::Native>{}); + native.template get<"number">().set(410); + + codec<schema::TestUnion, encode::KelSimple> codec; + + auto eov = codec.encode(native, simple); + SAW_EXPECT(eov.is_value(), "Encoding error"); + + // Reset values + native = {}; + + eov = codec.decode(simple, native); + SAW_EXPECT(eov.is_value(), "Decoding error"); + + SAW_EXPECT(native.template holds_alternative<"number">(), "Incorrect Decoding in array 0,1"); + SAW_EXPECT(native.template get<"number">().get() == 410, "Incorrect Decoding in number"); +} + SAW_TEST("KelSimple Tuple write and read back"){ using namespace saw; |