#pragma once #include namespace saw { namespace impl { template class json_encode { static_assert(always_false, "This schema type is not being handle by the json encoding."); }; template struct json_encode, RootSchema, FromEncode> { static error_or encode(const data, FromEncode>& from, buffer& to) { auto val = from.get(); std::array data; auto tc_result = std::to_chars(reinterpret_cast(data.data()), reinterpret_cast(data.data())+data.size(), val); if(tc_result.ec != std::errc{}){ return make_error(); } size_t bytes_written = 0; for(char* ptr = reinterpret_cast(data.data()); ptr != tc_result.ptr; ++ptr){ ++bytes_written; } auto& buff = to; error err = buff.write_require_length(bytes_written); if(!err.template is_type()){ return std::move(err); } for(char* ptr = reinterpret_cast(data.data()); ptr != tc_result.ptr; ++ptr){ uint8_t* un_ptr = reinterpret_cast(ptr); buff.push(un_ptr[0]); } return void_t{}; } }; template struct json_encode { static error_or encode(const data& from, buffer& to) { { auto err = to.push('"'); if(!err.template is_type()){ return err; } } for(std::size_t i = 0; i < from.size(); ++i){ auto err = to.push(from.get_at(i)); if(!err.template is_type()){ return err; } } { auto err = to.push('"'); if(!err.template is_type()){ return err; } } return void_t{}; } }; template struct json_encode, RootSchema, FromEncode> { template static error_or encode_element(const data, FromEncode>& from, buffer& to){ auto eov = json_encode::type, RootSchema, FromEncode>::encode(from.template get(), to); if(eov.is_error()){ return eov; } if constexpr ( (i+1) < sizeof...(T)){ { auto eov_ele = to.push(','); if(!eov_ele.template is_type()){ return eov_ele; } } { auto eov_ele = encode_element(from, to); if(eov_ele.is_error()){ return eov_ele; } } } return void_t{}; } static error_or encode(const data, FromEncode>& from, buffer& to) { { auto err = to.push('['); if(!err.template is_type()){ return err; } } if constexpr ( sizeof...(T) > 0 ){ auto eov = encode_element<0>(from, to); if(eov.is_error()){ return eov; } } { auto err = to.push(']'); if(!err.template is_type()){ return err; } } return void_t{}; } }; template struct json_encode, RootSchema, FromEncode> { template static error_or encode_level(const data, FromEncode>& from, buffer& to, std::array& index){ if constexpr (Level == D){ auto eov = json_encode::encode(from.at(index), to); if(eov.is_error()){ return eov; } } else { { auto err = to.push('['); if(!err.template is_type()){ return err; } } for(std::size_t i = 0; i < from.get_dim_size(Level); ++i){ if( i > 0 ){ auto err = to.push(','); if(!err.template is_type()){ return err; } } { index[Level] = i; auto eov = encode_level(from, to, index); if(eov.is_error()){ return eov; } } } { auto err = to.push(']'); if(!err.template is_type()){ return err; } } } return void_t{}; } static error_or encode(const data, FromEncode>& from, buffer& to) { std::array index; return encode_level<0>(from, to, index); } }; template struct json_encode...>, RootSchema, FromEncode> { template static error_or encode_element(const data...>, FromEncode>& from, buffer& to){ // Encode the name { std::string_view view = parameter_key_pack_type::literal.view(); error err = to.push('"'); if(!err.template is_type()){ return err; } err = to.push(*reinterpret_cast(view.data()), view.size()); if(!err.template is_type()){ return err; } err = to.push('"'); if(!err.template is_type()){ return err; } } // Add the separator { auto eov_ele = to.push(':'); if(!eov_ele.template is_type()){ return eov_ele; } } // Encode the value auto eov = json_encode::type, RootSchema, FromEncode>::encode(from.template get::literal>(), to); // Go to the next element if constexpr ( (i+1) < sizeof...(T)){ { auto eov_ele = to.push(','); if(!eov_ele.template is_type()){ return eov_ele; } } { auto eov_ele = encode_element(from, to); if(eov_ele.is_error()){ return eov_ele; } } } return void_t{}; } static error_or encode(const data...>, FromEncode>& from, buffer& to) { { auto err = to.push('{'); if(!err.template is_type()){ return err; } } if constexpr ( sizeof...(T) > 0 ){ auto eov = encode_element<0>(from, to); if(eov.is_error()){ return eov; } } { auto err = to.push('}'); if(!err.template is_type()){ return err; } } return void_t{}; } }; template struct json_encode...>, RootSchema, FromEncode> { template static error_or encode_element(const data...>, FromEncode>& from, buffer& to){ if(from.template holds_alternative::literal>()){ // Encode the name { std::string_view view = parameter_key_pack_type::literal.view(); error err = to.push('"'); if(!err.template is_type()){ return err; } err = to.push(*reinterpret_cast(view.data()), view.size()); if(!err.template is_type()){ return err; } err = to.push('"'); if(!err.template is_type()){ return err; } } // Add the separator { auto eov_ele = to.push(':'); if(!eov_ele.template is_type()){ return eov_ele; } } // Encode the value auto eov = json_encode::type, RootSchema, FromEncode>::encode(from.template get::literal>(), to); } // Go to the next element if constexpr ( (i+1) < sizeof...(T)){ { auto eov_ele = encode_element(from, to); if(eov_ele.is_error()){ return eov_ele; } } } return void_t{}; } static error_or encode(const data...>, FromEncode>& from, buffer& to) { { auto err = to.push('{'); if(!err.template is_type()){ return err; } } if constexpr ( sizeof...(T) > 0 ){ auto eov = encode_element<0>(from, to); if(eov.is_error()){ return eov; } } { auto err = to.push('}'); if(!err.template is_type()){ return err; } } return void_t{}; } }; template struct json_decode; template struct json_decode, RootSchema, ToDecode> { static error_or decode(buffer_view& buff, data, ToDecode>& to){ assert((buff.read() >= '0' && buff.read() <= '9') || buff.read() == '+' || buff.read() == '-'); std::size_t offset = 0; if(buff.read() == '-'){ ++offset; }else if(buff.read() == '+'){ return make_error(); } if (offset >= buff.read_composite_length()) { return make_error(); } if(buff.read(offset) >= '1' && buff.read(offset) <= '9'){ ++offset; if(offset >= buff.read_composite_length()){ return make_error(); } while(1){ if (buff.read(offset) >= '0' && buff.read(offset) <= '9'){ ++offset; if(offset >= buff.read_composite_length()){ break; } continue; } break; } }else if (buff.read(offset) == '0' ){ ++offset; }else{ return make_error(); } { std::string_view num_view{reinterpret_cast(&buff.read()), offset}; typename native_data_type>::type result; auto fc_result = std::from_chars(num_view.data(), num_view.data() + num_view.size(), result); if(fc_result.ec != std::errc{}){ return make_error(); } to.set(result); } buff.read_advance(offset); return void_t{}; } }; template struct json_decode, RootSchema, ToDecode> { template static error_or decode_level(buffer_view& buff, data, ToDecode>& to, std::array& index){ if constexpr (Level == D) { auto eov = json_decode::decode(buff, to.at(index)); if(eov.is_error()){ return eov; } } else { assert(buff.read() == '['); buff.read_advance(1); if( buff.read_composite_length() == 0 ){ return make_error(); } } return void_t{}; } static error_or decode(buffer_view& buff, data, ToDecode>& to){ std::array index; return decode_level<0>(buff, to, index); } }; } }