diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-12-04 12:18:14 +0100 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-12-04 12:18:14 +0100 |
commit | a14896f9ed209dd3f9597722e5a5697bd7dbf531 (patch) | |
tree | 089ca5cbbd206d1921f8f6b53292f5bc1902ca5c /modules/codec/simple.h | |
parent | 84ecdcbca9e55b1f57fbb832e12ff4fdbb86e7c9 (diff) |
meta: Renamed folder containing source
Diffstat (limited to 'modules/codec/simple.h')
-rw-r--r-- | modules/codec/simple.h | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/modules/codec/simple.h b/modules/codec/simple.h new file mode 100644 index 0000000..8760754 --- /dev/null +++ b/modules/codec/simple.h @@ -0,0 +1,389 @@ +#pragma once + +#include "data.h" +#include "stream_value.h" + +#include <forstio/core/buffer.h> +#include <forstio/core/error.h> + +namespace saw { +namespace encode { +struct KelSimple {}; +} + +template<typename T> +class data<T, encode::KelSimple> { +private: + ring_buffer buffer_; +public: + data() = default; + + buffer& get_buffer(){ + return buffer_; + } +}; + +namespace impl { +template<typename Schema, typename FromEnc> +class kelsimple_encode { + static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the kelsimple encoding."); +}; + +template<typename T, size_t N, typename FromEnc> +struct kelsimple_encode<schema::Primitive<T,N>, FromEnc> { + static error_or<void> encode(const data<schema::Primitive<T,N>, FromEnc>& from, buffer& to){ + auto eov = stream_value<schema::Primitive<T,N>>::encode(from.get(), to); + return eov; + } +}; + +template<typename T, size_t Dim, typename FromEnc> +struct kelsimple_encode<schema::Array<T,Dim>, FromEnc> { + template<std::size_t Level> + static error_or<void> encode_level(const data<schema::Array<T,Dim>, FromEnc>& from, buffer& to, std::array<std::size_t, Dim>& index){ + if constexpr (Dim == Level){ + return kelsimple_encode<T,FromEnc>::encode(from.at(index), to); + } else { + const std::size_t dim_size = from.get_dim_size(Level); + for(index[Level] = 0; (index.at(Level) < dim_size); ++index[Level]){ + auto eov = encode_level<Level+1>(from, to, index); + if(eov.is_error()){ + return eov; + } + } + } + return void_t{}; + } + + static error_or<void> encode(const data<schema::Array<T,Dim>, FromEnc>& from, buffer& to){ + { + for(uint64_t i = 0; i < Dim; ++i){ + auto eov = stream_value<schema::UInt64>::encode(from.get_dim_size(i), to); + if(eov.is_error()){ + return eov; + } + } + } + { + std::array<std::size_t, Dim> index; + std::fill(index.begin(), index.end(), 0); + + return encode_level<0>(from, to, index); + } + return void_t{}; + } +}; + +template<typename... T, string_literal... Lits, typename FromEnc> +struct kelsimple_encode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { + template<std::size_t i> + static error_or<void> encode_member(const data<schema::Struct<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; + { + 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::Struct<schema::Member<T,Lits>...>, FromEnc>& from, buffer& to){ + return encode_member<0>(from, to); + } +}; + +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> + static error_or<void> encode_member(const data<schema::Tuple<T...>, FromEnc>& from, buffer& to){ + using Type = typename parameter_pack_type<i,T...>::type; + { + auto eov = kelsimple_encode<Type, FromEnc>::encode(from.template get<i>(), to); + } + 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::Tuple<T...>, FromEnc>& from, buffer& to){ + return encode_member<0>(from, to); + } +}; + +template<typename FromEnc> +struct kelsimple_encode<schema::String, FromEnc> { + static error_or<void> encode(const data<schema::String, FromEnc>& from, buffer& to){ + const auto str_size = from.size(); + typename native_data_type<schema::UInt64>::type str_len = static_cast<uint64_t>(str_size); + { + auto eov = stream_value<schema::UInt64>::encode(str_len, to); + if(eov.is_error()){ + return eov; + } + } + + for(std::size_t i = 0; i < str_size; ++i){ + auto eov = stream_value<schema::Int8>::encode(from.at(i), to); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +template<typename Schema, typename FromEnc> +class kelsimple_decode { + static_assert(always_false<Schema, FromEnc>, "This schema type is not being handled by the kelsimple encoding."); +}; + +template<typename T, size_t N, typename FromEnc> +struct kelsimple_decode<schema::Primitive<T,N>, FromEnc> { + static error_or<void> decode(buffer& from, data<schema::Primitive<T,N>, FromEnc>& to){ + typename native_data_type<schema::Primitive<T,N>>::type val{}; + auto eov = stream_value<schema::Primitive<T,N>>::decode(val, from); + if (eov.is_value()) { + to.set(val); + } + return eov; + } + +}; + +template<typename T, size_t Dim, typename FromEnc> +struct kelsimple_decode<schema::Array<T,Dim>, FromEnc> { + template<std::size_t Level> + static error_or<void> decode_level(buffer& from, data<schema::Array<T,Dim>, FromEnc>& to, std::array<std::size_t, Dim>& index){ + if constexpr (Level == Dim){ + return kelsimple_decode<T, FromEnc>::decode(from, to.at(index)); + }else{ + const std::size_t dim_size = to.get_dim_size(Level); + for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ + auto eov = decode_level<Level+1>(from, to, index); + if(eov.is_error()){ + return eov; + } + } + } + return void_t{}; + } + + static error_or<void> decode(buffer& from, data<schema::Array<T,Dim>, FromEnc>& to){ + { + std::array<std::size_t, Dim> dims{}; + for(std::size_t i = 0; i < Dim; ++i){ + uint64_t val{}; + auto eov = stream_value<schema::UInt64>::decode(val, from); + if(eov.is_error()){ + return eov; + } + dims.at(i) = static_cast<std::size_t>(val); + } + to = data<schema::Array<T,Dim>,FromEnc>{dims}; + } + { + std::array<std::size_t, Dim> index{}; + return decode_level<0>(from, to, index); + } + return void_t{}; + } +}; +template<typename... T, string_literal... Lits, typename FromEnc> +struct kelsimple_decode<schema::Struct<schema::Member<T,Lits>...>,FromEnc> { + template<std::size_t i> + static error_or<void> decode_member(buffer& from, data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& to){ + using Type = typename parameter_pack_type<i,T...>::type; + 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); + if(eov.is_error()){ + return eov; + } + } + return void_t{}; + + } + static error_or<void> decode(buffer& from, data<schema::Struct<schema::Member<T,Lits>...>, FromEnc>& to){ + return decode_member<0>(from, to); + } + +}; + +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> + static error_or<void> decode_member(buffer& from, data<schema::Tuple<T...>, FromEnc>& to){ + using Type = typename parameter_pack_type<i,T...>::type; + { + auto eov = kelsimple_decode<Type, FromEnc>::decode(from, to.template get<i>()); + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = decode_member<i+1>(from, to); + if(eov.is_error()){ + return eov; + } + } + return void_t{}; + + } + static error_or<void> decode(buffer& from, data<schema::Tuple<T...>, FromEnc>& to){ + return decode_member<0>(from, to); + } + +}; +template<typename FromEnc> +struct kelsimple_decode<schema::String, FromEnc> { + static error_or<void> decode(buffer& from, data<schema::String, FromEnc>& to){ + { + uint64_t val{}; + auto eov = stream_value<schema::UInt64>::decode(val, from); + if(eov.is_error()){ + return eov; + } + to = data<schema::String,FromEnc>{val}; + } + const std::size_t str_size = to.size(); + for(std::size_t i = 0; i < str_size; ++i){ + int8_t val{}; + auto eov = stream_value<schema::Int8>::decode(val, from); + if(eov.is_error()){ + return eov; + } + to.set_at(i, val); + } + return void_t{}; + } +}; + +} + +template<typename Schema> +class codec<Schema, encode::KelSimple> { +public: + struct config { + size_t depth = 16; + size_t length = 1024; + }; +private: + config cfg_; +public: + codec() = default; + + SAW_FORBID_COPY(codec); + SAW_DEFAULT_MOVE(codec); + + template<typename FromEnc> + error_or<void> encode(const data<Schema, FromEnc>& from_enc, data<Schema, encode::KelSimple>& to_enc){ + buffer_view buff_v{to_enc.get_buffer()}; + + auto eov = impl::kelsimple_encode<Schema, FromEnc>::encode(from_enc, buff_v); + + to_enc.get_buffer().write_advance(buff_v.write_offset()); + + return eov; + } + + template<typename ToDec> + error_or<void> decode(data<Schema, encode::KelSimple>& from_dec, data<Schema, ToDec>& to){ + buffer_view buff_v{from_dec.get_buffer()}; + + auto eov = impl::kelsimple_decode<Schema,ToDec>::decode(buff_v, to); + + return eov; + } +}; +} |