summaryrefslogtreecommitdiff
path: root/src/codec-json
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec-json')
-rw-r--r--src/codec-json/json.tmpl.h99
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{};
}
};