diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-06-29 10:48:32 +0200 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2023-06-29 10:48:32 +0200 |
commit | e2b2f8b9a395a235e26e4b449b3498a2c0410f8f (patch) | |
tree | f0fd1487a3d5010a5e4daf3f4f8052a77f82029c /src | |
parent | 95b870c811032436c209978d0e2fb6ab76707e8e (diff) |
c++,codec-json: Added Struct decoding
Diffstat (limited to 'src')
-rw-r--r-- | src/codec-json/json.tmpl.h | 99 |
1 files changed, 98 insertions, 1 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{}; } }; |