summaryrefslogtreecommitdiff
path: root/modules/codec/simple.h
diff options
context:
space:
mode:
Diffstat (limited to 'modules/codec/simple.h')
-rw-r--r--modules/codec/simple.h389
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;
+ }
+};
+}