diff options
-rw-r--r-- | src/codec-json/json.tmpl.h | 99 | ||||
-rw-r--r-- | tests/codec-json.cpp | 5 |
2 files changed, 100 insertions, 4 deletions
diff --git a/src/codec-json/json.tmpl.h b/src/codec-json/json.tmpl.h index 8fb01a9..6cf7189 100644 --- a/src/codec-json/json.tmpl.h +++ b/src/codec-json/json.tmpl.h @@ -461,9 +461,106 @@ struct json_decode<schema::String, RootSchema, ToDecode> { template<typename... T, string_literal... Lits, typename RootSchema, typename ToDecode> struct json_decode<schema::Struct<schema::Member<T,Lits>...>, RootSchema, ToDecode> { + template<std::size_t i> + static error_or<void> decode_field_search(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields, const data<schema::String,ToDecode>& search_name){ + if constexpr ( i < sizeof...(T)){ + using Type = typename parameter_pack_type<i, T...>::type; + constexpr static string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + if(search_name == Literal.view()){ + if(fields[i]){ + // TODO Change to this + // return make_error<err::already_exists>(); + return make_error<err::invalid_state>(); + } + fields[i] = true; + auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<Literal>()); + if(eov.is_error()){ + return eov; + } + }else { + decode_field_search<i+1>(buff, to, fields, search_name); + } + }else { + return make_error<err::invalid_state>(); + } + return void_t{}; + } + + static error_or<void> decode_fields(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to, std::array<bool, sizeof...(T)>& fields){ + for(;;){ + data<schema::String, ToDecode> name; + auto eov = json_decode<schema::String, RootSchema, ToDecode>::decode(buff, name); + if(eov.is_error()){ + return eov; + } + json_helper::skip_whitespace(buff); + if(buff.read_composite_length() == 0){ + return make_error<err::buffer_exhausted>(); + } + if(buff.read() != ':'){ + return make_error<err::invalid_state>(); + } + buff.read_advance(1); + json_helper::skip_whitespace(buff); + if(buff.read_composite_length() == 0){ + return make_error<err::buffer_exhausted>(); + } + { + auto eov = decode_field_search<0>(buff, to, fields, name); + if(eov.is_error()){ + return eov; + } + } + json_helper::skip_whitespace(buff); + if(buff.read_composite_length() == 0){ + return make_error<err::buffer_exhausted>(); + } + if(buff.read() == ','){ + buff.read_advance(1); + }else if(buff.read() == '}'){ + // If not all fields are set, the dataset is incomplete + for(auto& iter : fields){ + if(!iter){ + return make_error<err::invalid_state>(); + } + } + buff.read_advance(1); + return void_t{}; + }else{ + return make_error<err::invalid_state>(); + } + json_helper::skip_whitespace(buff); + if(buff.read_composite_length() == 0){ + return make_error<err::buffer_exhausted>(); + } + } + return void_t{}; + } + static error_or<void> decode(buffer_view& buff, data<schema::Struct<schema::Member<T,Lits>...>, ToDecode>& to){ + std::array<bool, sizeof...(T)> found_fields; + std::fill(found_fields.begin(), found_fields.end(), false); + + assert(buff.read() == '{'); + buff.read_advance(1); + json_helper::skip_whitespace(buff); + if(buff.read_composite_length() == 0){ + return make_error<err::buffer_exhausted>(); + } + if(buff.read() == '}'){ + if(sizeof...(T) > 0){ + return make_error<err::invalid_state>(); + } + buff.read_advance(1); + return void_t{}; + } - return make_error<err::not_implemented>(); + auto eov = decode_fields(buff, to, found_fields); + if(eov.is_error()){ + return eov; + } + + return void_t{}; } }; diff --git a/tests/codec-json.cpp b/tests/codec-json.cpp index 5b4700f..926f550 100644 --- a/tests/codec-json.cpp +++ b/tests/codec-json.cpp @@ -285,7 +285,7 @@ SAW_TEST("Three Dim Array write and read"){ } -SAW_TEST("Struct write"){ +SAW_TEST("Struct read and write"){ using namespace saw; data<schema::TestStruct, encode::Native> native; data<schema::TestStruct, encode::Json> json; @@ -302,13 +302,12 @@ SAW_TEST("Struct write"){ std::string enc_val = convert_to_string(json.get_buffer()); SAW_EXPECT(enc_val == str_v, std::string{"Struct not encoded correctly. Encoded: "} + enc_val + std::string{" Expected: "} + std::string{str_v}); -/* + native = {}; eov = json_codec.decode(json, native); SAW_EXPECT(eov.is_value(), "Decoding error"); SAW_EXPECT(native.get<"foo">().get() == 5, "Invalid value for foo"); SAW_EXPECT(native.get<"bar">() == "baz", "Invalid value for bar"); -*/ } SAW_TEST("Int8 read"){ |