#pragma once #include "data.hpp" #include "stream_value.hpp" #include #include namespace saw { namespace encode { struct KelSimple { static constexpr string_literal name = "encode::KelSimple"; }; } template class data { private: own buffer_; public: data(): buffer_{heap()} {} data(own buffer__): buffer_{std::move(buffer__)} {} buffer& get_buffer(){ return *buffer_; } }; namespace impl { template class kelsimple_encode { static_assert(always_false, "This schema type is not being handled by the kelsimple encoding."); }; template struct kelsimple_encode, FromEnc> { static error_or encode(const data, FromEnc>& from, buffer& to){ auto eov = stream_value>::encode(from.get(), to); return eov; } }; template struct kelsimple_encode, FromEnc> { template static error_or encode_level(const data, FromEnc>& from, buffer& to, std::array& index){ if constexpr (Dim == Level){ return kelsimple_encode::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(from, to, index); if(eov.is_error()){ return eov; } } } return void_t{}; } static error_or encode(const data, FromEnc>& from, buffer& to){ { for(uint64_t i = 0; i < Dim; ++i){ auto eov = stream_value::encode(from.get_dim_size(i), to); if(eov.is_error()){ return eov; } } } { std::array index; std::fill(index.begin(), index.end(), 0); return encode_level<0>(from, to, index); } return void_t{}; } }; template struct kelsimple_encode...>,FromEnc> { template static error_or encode_member(const data...>, FromEnc>& from, buffer& to){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { auto eov = kelsimple_encode::encode(from.template get(), to); if(eov.is_error()){ return eov; } } if constexpr ((i+1) < sizeof...(T)){ auto eov = encode_member(from, to); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or encode(const data...>, FromEnc>& from, buffer& to){ return encode_member<0>(from, to); } }; template struct kelsimple_encode...>,FromEnc> { template static error_or encode_member(const data...>, FromEnc>& from, buffer& to){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; if (from.template holds_alternative()) { { auto eov = stream_value::encode(static_cast(i), to); if(eov.is_error()){ return eov; } } { auto eov = kelsimple_encode::encode(from.template get(), to); if(eov.is_error()){ return eov; } } } if constexpr ( (i+1) < sizeof...(T) ){ auto eov = encode_member(from, to); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or encode(const data...>, FromEnc>& from, buffer& to){ return encode_member<0>(from, to); } }; template struct kelsimple_encode, FromEnc> { template static error_or encode_member(const data, FromEnc>& from, buffer& to){ using Type = typename parameter_pack_type::type; { auto eov = kelsimple_encode::encode(from.template get(), to); } if constexpr ((i+1) < sizeof...(T)){ auto eov = encode_member(from, to); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or encode(const data, FromEnc>& from, buffer& to){ return encode_member<0>(from, to); } }; template struct kelsimple_encode { static error_or encode(const data& from, buffer& to){ const auto str_size = from.size(); typename native_data_type::type str_len = static_cast(str_size); { auto eov = stream_value::encode(str_len, to); if(eov.is_error()){ return eov; } } for(std::size_t i = 0; i < str_size; ++i){ auto eov = stream_value::encode(from.at(i), to); if(eov.is_error()){ return eov; } } return void_t{}; } }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template class kelsimple_decode { static_assert(always_false, "This schema type is not being handled by the kelsimple encoding."); }; template struct kelsimple_decode, FromEnc> { static error_or decode(buffer& from, data, FromEnc>& to){ typename native_data_type>::type val{}; auto eov = stream_value>::decode(val, from); if (eov.is_value()) { to.set(val); } return eov; } }; template struct kelsimple_decode, FromEnc> { template static error_or decode_level(buffer& from, data, FromEnc>& to, std::array& index){ if constexpr (Level == Dim){ return kelsimple_decode::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(from, to, index); if(eov.is_error()){ return eov; } } } return void_t{}; } static error_or decode(buffer& from, data, FromEnc>& to){ { std::array dims{}; for(std::size_t i = 0; i < Dim; ++i){ uint64_t val{}; auto eov = stream_value::decode(val, from); if(eov.is_error()){ return eov; } dims.at(i) = static_cast(val); } to = data,FromEnc>{dims}; } { std::array index{}; return decode_level<0>(from, to, index); } return void_t{}; } }; template struct kelsimple_decode...>,FromEnc> { template static error_or decode_member(buffer& from, data...>, FromEnc>& to){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { auto eov = kelsimple_decode::decode(from, to.template get()); if(eov.is_error()){ return eov; } } if constexpr ((i+1) < sizeof...(T)){ auto eov = decode_member(from, to); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or decode(buffer& from, data...>, FromEnc>& to){ return decode_member<0>(from, to); } }; template struct kelsimple_decode...>,FromEnc> { template static error_or decode_member(buffer& from, data...>, FromEnc>& to, uint64_t val){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; if( i == val ){ to.template set(data{}); auto eov = kelsimple_decode::decode(from, to.template get()); if(eov.is_error()){ return eov; } return void_t{}; } if constexpr ((i+1) < sizeof...(T)){ auto eov = decode_member(from, to, val); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or decode(buffer& from, data...>, FromEnc>& to){ uint64_t val{}; auto eov = stream_value::decode(val, from); if(eov.is_error()){ return eov; } if ( val >= sizeof...(T) ){ return make_error(); } return decode_member<0>(from, to, val); } }; template struct kelsimple_decode,FromEnc> { template static error_or decode_member(buffer& from, data, FromEnc>& to){ using Type = typename parameter_pack_type::type; { auto eov = kelsimple_decode::decode(from, to.template get()); } if constexpr ((i+1) < sizeof...(T)){ auto eov = decode_member(from, to); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or decode(buffer& from, data, FromEnc>& to){ return decode_member<0>(from, to); } }; template struct kelsimple_decode { static error_or decode(buffer& from, data& to){ { uint64_t val{}; auto eov = stream_value::decode(val, from); if(eov.is_error()){ return eov; } to = data{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::decode(val, from); if(eov.is_error()){ return eov; } to.set_at(i, val); } return void_t{}; } }; } template class codec { 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 error_or encode(const data& from_enc, data& to_enc){ buffer_view buff_v{to_enc.get_buffer()}; auto eov = impl::kelsimple_encode::encode(from_enc, buff_v); to_enc.get_buffer().write_advance(buff_v.write_offset()); return eov; } template error_or decode(data& from_dec, data& to){ buffer_view buff_v{from_dec.get_buffer()}; auto eov = impl::kelsimple_decode::decode(buff_v, to); return eov; } }; }