summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudius Holeksa <mail@keldu.de>2023-06-27 12:41:56 +0200
committerClaudius Holeksa <mail@keldu.de>2023-06-27 12:41:56 +0200
commit5688c721c610e2a8931d6ec6f84dee2d4d65c763 (patch)
tree3d38ec081061f2d6226a12af93ee092f27882d8c
parent7668b8aceb42b5a46e1f9ca36d16dbfabe291748 (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.h14
-rw-r--r--src/codec/simple.h81
-rw-r--r--src/core/templates.h5
-rw-r--r--tests/codec.cpp30
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;