summaryrefslogtreecommitdiff
path: root/src/codec-json
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec-json')
-rw-r--r--src/codec-json/.nix/derivation.nix32
-rw-r--r--src/codec-json/SConscript38
-rw-r--r--src/codec-json/SConstruct66
-rw-r--r--src/codec-json/json.h116
-rw-r--r--src/codec-json/json.tmpl.h734
5 files changed, 0 insertions, 986 deletions
diff --git a/src/codec-json/.nix/derivation.nix b/src/codec-json/.nix/derivation.nix
deleted file mode 100644
index 0f701c9..0000000
--- a/src/codec-json/.nix/derivation.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{ lib
-, stdenvNoCC
-, scons
-, clang
-, clang-tools
-, version
-, forstio
-}:
-
-let
-
-in stdenvNoCC.mkDerivation {
- pname = "forstio-codec-json";
- inherit version;
- src = ./..;
-
- enableParallelBuilding = true;
-
- nativeBuildInputs = [
- scons
- clang
- clang-tools
- ];
-
- buildInputs = [
- forstio.core
- forstio.async
- forstio.codec
- ];
-
- outputs = ["out" "dev"];
-}
diff --git a/src/codec-json/SConscript b/src/codec-json/SConscript
deleted file mode 100644
index 772ac0b..0000000
--- a/src/codec-json/SConscript
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/false
-
-import os
-import os.path
-import glob
-
-
-Import('env')
-
-dir_path = Dir('.').abspath
-
-# Environment for base library
-codec_json_env = env.Clone();
-
-codec_json_env.sources = sorted(glob.glob(dir_path + "/*.cpp"))
-codec_json_env.headers = sorted(glob.glob(dir_path + "/*.h"))
-
-env.sources += codec_json_env.sources;
-env.headers += codec_json_env.headers;
-
-## Shared lib
-objects_shared = []
-codec_json_env.add_source_files(objects_shared, codec_json_env.sources, shared=True);
-codec_json_env.library_shared = codec_json_env.SharedLibrary('#build/forstio-codec-json', [objects_shared]);
-
-## Static lib
-objects_static = []
-codec_json_env.add_source_files(objects_static, codec_json_env.sources, shared=False);
-codec_json_env.library_static = codec_json_env.StaticLibrary('#build/forstio-codec-json', [objects_static]);
-
-# Set Alias
-env.Alias('library_codec_json', [codec_json_env.library_shared, codec_json_env.library_static]);
-
-env.targets += ['library_codec_json'];
-
-# Install
-env.Install('$prefix/lib/', [codec_json_env.library_shared, codec_json_env.library_static]);
-env.Install('$prefix/include/forstio/codec/json/', [codec_json_env.headers]);
diff --git a/src/codec-json/SConstruct b/src/codec-json/SConstruct
deleted file mode 100644
index edd5f57..0000000
--- a/src/codec-json/SConstruct
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-import os
-import os.path
-import glob
-import re
-
-
-if sys.version_info < (3,):
- def isbasestring(s):
- return isinstance(s,basestring)
-else:
- def isbasestring(s):
- return isinstance(s, (str,bytes))
-
-def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""):
-
- if isbasestring(filetype):
- dir_path = self.Dir('.').abspath
- filetype = sorted(glob.glob(dir_path+"/"+filetype))
-
- for path in filetype:
- target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path )
- if shared:
- target_name+='.os'
- sources.append( self.SharedObject( target=target_name, source=path ) )
- else:
- target_name+='.o'
- sources.append( self.StaticObject( target=target_name, source=path ) )
- pass
-
-def isAbsolutePath(key, dirname, env):
- assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,)
-
-env_vars = Variables(
- args=ARGUMENTS
-)
-
-env_vars.Add('prefix',
- help='Installation target location of build results and headers',
- default='/usr/local/',
- validator=isAbsolutePath
-)
-
-env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[],
- CPPDEFINES=['SAW_UNIX'],
- CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'],
- LIBS=['forstio-codec'])
-env.__class__.add_source_files = add_kel_source_files
-env.Tool('compilation_db');
-env.cdb = env.CompilationDatabase('compile_commands.json');
-
-env.objects = [];
-env.sources = [];
-env.headers = [];
-env.targets = [];
-
-Export('env')
-SConscript('SConscript')
-
-env.Alias('cdb', env.cdb);
-env.Alias('all', [env.targets]);
-env.Default('all');
-
-env.Alias('install', '$prefix')
diff --git a/src/codec-json/json.h b/src/codec-json/json.h
deleted file mode 100644
index 1fe6bb5..0000000
--- a/src/codec-json/json.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#pragma once
-
-#include <forstio/core/buffer.h>
-#include <forstio/core/common.h>
-#include <forstio/codec/data.h>
-
-#include <algorithm>
-
-namespace saw {
-namespace encode {
-struct Json {};
-}
-
-template<typename Schema>
-class data<Schema, encode::Json> {
-private:
- ring_buffer buffer_;
-public:
- data():buffer_{}{}
-
- data(std::size_t ring_size_):buffer_{ring_size_}{}
-
- data(const std::string_view& view__):
- buffer_{view__.size()}
- {
- auto ptr = reinterpret_cast<const uint8_t*>(view__.data());
- if(!ptr){
- return;
- }
- buffer_.push(*ptr, view__.size());
- }
-
- buffer& get_buffer(){
- return buffer_;
- }
-
- const buffer& get_buffer() const {
- return buffer_;
- }
-
- error push(uint8_t val){
- return buffer_.push(val);
- }
-
- std::size_t get_size() const {
- return buffer_.read_composite_length();
- }
-
- uint8_t& at(std::size_t i){
- return buffer_.read(i);
- }
-
- const uint8_t& at(std::size_t i) const {
- return buffer_.read(i);
- }
-};
-}
-
-#include "json.tmpl.h"
-
-namespace saw {
-
-/**
- * Codec class for json
- */
-template<typename Schema>
-class codec<Schema, encode::Json> {
-public:
- struct config {
- size_t depth = 16;
- size_t length = 1024;
- };
-private:
- config cfg_;
-public:
- /**
- * Default constructor
- */
- codec(){}
-
- /**
- * Constructor
- */
- codec(config cfg__):cfg_{std::move(cfg__)}{}
-
- SAW_FORBID_COPY(codec);
- SAW_DEFAULT_MOVE(codec);
-
- template <typename FromEncoding>
- error_or<void> encode(const data<Schema, FromEncoding>& from_encode, data<Schema, encode::Json>& to_encode){
- // To Be encoded
- buffer_view buff_v{to_encode.get_buffer()};
- auto eov = impl::json_encode<Schema, Schema, FromEncoding>::encode(from_encode, buff_v);
- if(eov.is_error()){
- return std::move(eov.get_error());
- }
- to_encode.get_buffer().write_advance(buff_v.write_offset());
-
- return void_t{};
- }
-
- template <typename ToEncoding>
- error_or<void> decode(data<Schema, encode::Json>& from_decode, data<Schema, ToEncoding>& to_decode){
- buffer_view buff_v{from_decode.get_buffer()};
-
- auto eov = impl::json_decode<Schema, Schema, ToEncoding>::decode(buff_v, to_decode);
- if(eov.is_error()){
- return std::move(eov.get_error());
- }
- from_decode.get_buffer().read_advance(buff_v.read_offset());
-
- return void_t {};
- }
-};
-}
-
diff --git a/src/codec-json/json.tmpl.h b/src/codec-json/json.tmpl.h
deleted file mode 100644
index 4b3a1a2..0000000
--- a/src/codec-json/json.tmpl.h
+++ /dev/null
@@ -1,734 +0,0 @@
-#pragma once
-
-#include <charconv>
-#include <sstream>
-
-#include <iostream>
-
-namespace saw {
-namespace impl {
-template<typename Schema, typename RootSchema, typename FromEncode>
-class json_encode {
- static_assert(always_false<Schema, RootSchema, FromEncode>, "This schema type is not being handled by the json encoding.");
-};
-
-template<typename T, size_t N, typename RootSchema, typename FromEncode>
-struct json_encode<schema::Primitive<T,N>, RootSchema, FromEncode> {
- static error_or<void> encode(const data<schema::Primitive<T,N>, FromEncode>& from, buffer& to) {
- auto val = from.get();
- std::array<uint8_t, 256> data;
- auto tc_result = std::to_chars(reinterpret_cast<char*>(data.data()), reinterpret_cast<char*>(data.data())+data.size(), val);
-
- if(tc_result.ec != std::errc{}){
- return make_error<err::critical>();
- }
-
- size_t bytes_written = 0;
- for(char* ptr = reinterpret_cast<char*>(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<err::no_error>()){
- return std::move(err);
- }
-
- for(char* ptr = reinterpret_cast<char*>(data.data()); ptr != tc_result.ptr; ++ptr){
- uint8_t* un_ptr = reinterpret_cast<uint8_t*>(ptr);
- buff.push(un_ptr[0]);
- }
-
- return void_t{};
- }
-};
-
-template<typename RootSchema, typename FromEncode>
-struct json_encode<schema::String, RootSchema, FromEncode> {
- static error_or<void> encode(const data<schema::String, FromEncode>& from, buffer& to) {
- {
- auto err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- 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<err::no_error>()){
- return err;
- }
- }
- {
- auto err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- }
-
- return void_t{};
- }
-};
-
-template<typename... T, typename RootSchema, typename FromEncode>
-struct json_encode<schema::Tuple<T...>, RootSchema, FromEncode> {
- template<size_t i>
- static error_or<void> encode_element(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to){
- auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<i>(), to);
-
- if(eov.is_error()){
- return eov;
- }
-
- if constexpr ( (i+1) < sizeof...(T)){
- {
- auto eov_ele = to.push(',');
- if(!eov_ele.template is_type<err::no_error>()){
- return eov_ele;
- }
- }
- {
- auto eov_ele = encode_element<i+1>(from, to);
- if(eov_ele.is_error()){
- return eov_ele;
- }
- }
-
-
- }
- return void_t{};
- }
-
- static error_or<void> encode(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to) {
- {
- auto err = to.push('[');
- if(!err.template is_type<err::no_error>()){
- 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<err::no_error>()){
- return err;
- }
- }
-
- return void_t{};
- }
-};
-
-template<typename T, size_t D, typename RootSchema, typename FromEncode>
-struct json_encode<schema::Array<T,D>, RootSchema, FromEncode> {
- template<size_t Level>
- static error_or<void> encode_level(const data<schema::Array<T,D>, FromEncode>& from, buffer& to, std::array<std::size_t, D>& index){
- if constexpr (Level == D){
- auto eov = json_encode<T, RootSchema, FromEncode>::encode(from.at(index), to);
- if(eov.is_error()){
- return eov;
- }
- } else {
- {
- auto err = to.push('[');
- if(!err.template is_type<err::no_error>()){
- 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<err::no_error>()){
- return err;
- }
- }
- {
- index[Level] = i;
- auto eov = encode_level<Level+1>(from, to, index);
- if(eov.is_error()){
- return eov;
- }
- }
- }
- {
- auto err = to.push(']');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- }
- }
- return void_t{};
- }
-
- static error_or<void> encode(const data<schema::Array<T,D>, FromEncode>& from, buffer& to) {
- std::array<std::size_t, D> index;
- return encode_level<0>(from, to, index);
- }
-};
-
-template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode>
-struct json_encode<schema::Struct<schema::Member<T,Key>...>, RootSchema, FromEncode> {
-
- template<size_t i>
- static error_or<void> encode_element(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){
- // Encode the name
- {
- std::string_view view = parameter_key_pack_type<i, Key...>::literal.view();
- error err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size());
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- }
- // Add the separator
- {
- auto eov_ele = to.push(':');
- if(!eov_ele.template is_type<err::no_error>()){
- return eov_ele;
- }
- }
-
- // Encode the value
- auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to);
-
- // Go to the next element
- if constexpr ( (i+1) < sizeof...(T)){
- {
- auto eov_ele = to.push(',');
- if(!eov_ele.template is_type<err::no_error>()){
- return eov_ele;
- }
- }
- {
- auto eov_ele = encode_element<i+1>(from, to);
- if(eov_ele.is_error()){
- return eov_ele;
- }
- }
-
-
- }
-
- return void_t{};
- }
- static error_or<void> encode(const data<schema::Struct<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) {
- {
- auto err = to.push('{');
- if(!err.template is_type<err::no_error>()){
- 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<err::no_error>()){
- return err;
- }
- }
-
- return void_t{};
- }
-};
-
-template<typename... T, string_literal... Key, typename RootSchema, typename FromEncode>
-struct json_encode<schema::Union<schema::Member<T,Key>...>, RootSchema, FromEncode> {
-
- template<size_t i>
- static error_or<void> encode_element(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to){
- if(from.template holds_alternative<typename parameter_key_pack_type<i, Key...>::literal>()){
- // Encode the name
- {
- std::string_view view = parameter_key_pack_type<i, Key...>::literal.view();
- error err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- err = to.push(*reinterpret_cast<const uint8_t *>(view.data()), view.size());
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- err = to.push('"');
- if(!err.template is_type<err::no_error>()){
- return err;
- }
- }
- // Add the separator
- {
- auto eov_ele = to.push(':');
- if(!eov_ele.template is_type<err::no_error>()){
- return eov_ele;
- }
- }
-
- // Encode the value
- auto eov = json_encode<typename parameter_pack_type<i, T...>::type, RootSchema, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to);
- }
- // Go to the next element
- if constexpr ( (i+1) < sizeof...(T)){
- {
- auto eov_ele = encode_element<i+1>(from, to);
- if(eov_ele.is_error()){
- return eov_ele;
- }
- }
-
-
- }
-
- return void_t{};
- }
- static error_or<void> encode(const data<schema::Union<schema::Member<T,Key>...>, FromEncode>& from, buffer& to) {
- {
- auto err = to.push('{');
- if(!err.template is_type<err::no_error>()){
- 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<err::no_error>()){
- return err;
- }
- }
-
- return void_t{};
- }
-};
-
-struct json_helper {
- static bool is_whitespace(int8_t ch) {
- return ch == '\t' || ch == ' ' || ch == '\r' || ch == '\n';
- }
-
- static void skip_whitespace(buffer_view& buff) {
- while(buff.read_composite_length() > 0 && json_helper::is_whitespace(buff.read())) {
- buff.read_advance(1);
- }
- }
-};
-
-template<typename Schema, typename RootSchema, typename ToDecode>
-struct json_decode;
-
-template<typename T, size_t N, typename RootSchema, typename ToDecode>
-struct json_decode<schema::Primitive<T,N>, RootSchema, ToDecode> {
- static error_or<void> decode(buffer_view& buff, data<schema::Primitive<T,N>, 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<err::not_supported>();
- }
- if (offset >= buff.read_composite_length()) {
- return make_error<err::buffer_exhausted>();
- }
- if (buff.read(offset) >= '1' && buff.read(offset) <= '9') {
- ++offset;
-
- if(offset >= buff.read_composite_length()) {
- return make_error<err::buffer_exhausted>();
- }
-
- 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<err::buffer_exhausted>();
- }
-
- {
- std::string_view num_view{reinterpret_cast<char*>(&buff.read()), offset};
- typename native_data_type<schema::Primitive<T,N>>::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<err::invalid_state>();
- }
-
- to.set(result);
- }
- buff.read_advance(offset);
-
- return void_t{};
- }
-};
-
-template<typename RootSchema, typename ToDecode>
-struct json_decode<schema::String, RootSchema, ToDecode> {
- static error_or<void> decode(buffer_view& buff, data<schema::String, ToDecode>& to){
- assert(buff.read() == '"');
- buff.read_advance(1);
-
- std::stringstream iss;
- bool string_done = false;
- while(!string_done){
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
-
- switch(buff.read()){
- case '\\':{
- buff.read_advance(1);
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
- switch(buff.read()){
- case '\\':
- case '/':
- case '"':
- iss<< buff.read();
- break;
- case 'b':
- iss<<'\b';
- break;
- case 'f':
- iss<<'\f';
- break;
- case 'n':
- iss<<'\n';
- break;
- case 'r':
- iss<<'\r';
- break;
- case 't':
- iss<<'\t';
- break;
- case 'u': {
- buff.read_advance(1);
- if(buff.read_composite_length() < 4){
- return make_error<err::buffer_exhausted>();
- }
- iss<<'?';
- iss<<'?';
- iss<<'?';
- iss<<'?';
-
- buff.read_advance(3);
- } break;
- }
- } break;
- case '"':
- string_done = true;
- break;
- default:{
- // Avoids Control sequences
- if(buff.read() >= ' ' && buff.read() <= '~'){
- iss<<buff.read();
- }
- // Avoid Unicode
- else if (buff.read() < 0) {
- do {
- buff.read_advance(1);
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
- } while( buff.read() < 0 );
- iss<<'?';
- }
- break;
- }
- }
- buff.read_advance(1);
- }
-
- std::string raw = iss.str();
- to.set(std::move(raw));
-
- return void_t{};
- }
-};
-
-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]){
- 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>();
- }
-
- // Check if there are no elements present in the JSON Struct
- if(buff.read() == '}'){
- if(sizeof...(T) > 0){
- return make_error<err::invalid_state>();
- }
- buff.read_advance(1);
- return void_t{};
- }
-
- auto eov = decode_fields(buff, to, found_fields);
- if(eov.is_error()){
- return eov;
- }
-
- return void_t{};
- }
-};
-
-template<typename... T, typename RootSchema, typename ToDecode>
-struct json_decode<schema::Tuple<T...>, RootSchema, ToDecode> {
- template<std::size_t i>
- static error_or<void> decode_element(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){
- if constexpr (i < sizeof...(T)){
- if constexpr ( i > 0 ){
- if(buff.read() != ','){
- return make_error<err::invalid_state>();
- }
- buff.read_advance(1);
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
- }
- using Type = typename parameter_pack_type<i, T...>::type;
-
- auto eov = json_decode<Type, RootSchema, ToDecode>::decode(buff, to.template get<i>());
- if(eov.is_error()){
- return eov;
- }
- json_helper::skip_whitespace(buff);
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
-
- eov = decode_element<i+1>(buff, to);
- if(eov.is_error()){
- return eov;
- }
- }else{
- if(buff.read() != ']'){
- return make_error<err::invalid_state>();
- }
- buff.read_advance(1);
- }
- return void_t{};
- }
-
- static error_or<void> decode(buffer_view& buff, data<schema::Tuple<T...>, ToDecode>& to){
- assert(buff.read() == '[');
- buff.read_advance(1);
-
- json_helper::skip_whitespace(buff);
- if(buff.read_composite_length() == 0){
- return make_error<err::buffer_exhausted>();
- }
-
- auto eov = decode_element<0>(buff, to);
- if(eov.is_error()){
- return eov;
- }
-
- return void_t{};
- }
-};
-
-// The whole std::vector approach is hacky af. ToDo change it maybe?
-template<typename T, size_t D, typename RootSchema, typename ToDecode>
-struct json_decode<schema::Array<T,D>, RootSchema, ToDecode> {
- template<size_t Level>
- static error_or<void> decode_flat_level(buffer_view& buff, std::vector<data<T, encode::Native>>& to, std::array<std::size_t, D>& index, std::array<std::size_t, D>& dims, bool log_dim){
- if constexpr (Level == D) {
- json_helper::skip_whitespace(buff);
- try {
- to.push_back({});
- }catch(std::exception& e){
- return make_error<err::out_of_memory>();
- }
- auto eov = json_decode<T, RootSchema, ToDecode>::decode(buff, to.back());
- if(eov.is_error()){
- return eov;
- }
- } else {
- assert(buff.read() == '[');
- buff.read_advance(1);
-
- json_helper::skip_whitespace(buff);
- if ( buff.read_composite_length() == 0 ){
- return make_error<err::buffer_exhausted>();
- }
-
- index[Level] = 0;
- for(;;){
- // We should have an element right now
- auto eov = decode_flat_level<Level+1>(buff,to,index,dims, index[Level] == 0 && log_dim);
- if(eov.is_error()){
- return eov;
- }
- json_helper::skip_whitespace(buff);
- if ( buff.read_composite_length() == 0 ){
- return make_error<err::buffer_exhausted>();
- }
-
- ++index[Level];
- if(buff.read() == ','){
- buff.read_advance(1);
- } else if(buff.read() == ']'){
- buff.read_advance(1);
- break;
- } else {
- return make_error<err::invalid_state>();
- }
- json_helper::skip_whitespace(buff);
- if ( buff.read_composite_length() == 0 ){
- return make_error<err::buffer_exhausted>();
- }
- }
- if(log_dim){
- dims[Level] = index[Level];
- }else if (dims[Level] != index[Level]){
- return make_error<err::invalid_state>();
- }
- }
- return void_t{};
- }
-
- template<std::size_t Level>
- static error_or<void> decode_unflat_level(std::vector<data<T,encode::Native>>& flat, data<schema::Array<T,D>, ToDecode>& to, std::array<std::size_t, D>& index, std::size_t& flat_index) {
- if constexpr ( Level == D ){
- auto& flat_data = flat.at(flat_index);
- to.at(index) = std::move(flat_data);
- ++flat_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_unflat_level<Level+1>(flat, to, index, flat_index);
- if(eov.is_error()){
- return eov;
- }
- }
- }
- return void_t{};
- }
-
- static error_or<void> decode(buffer_view& buff, data<schema::Array<T,D>, ToDecode>& to){
- std::array<std::size_t, D> index;
- std::array<std::size_t, D> dims;
- std::fill(dims.begin(), dims.end(), 0);
- std::vector<data<T,encode::Native>> flat_array;
- auto eov = decode_flat_level<0>(buff, flat_array, index, dims, true);
- if(eov.is_error()){
- return eov;
- }
-
- to = {dims};
- std::size_t flat_index = 0;
-
- return decode_unflat_level<0>(flat_array, to, index, flat_index);
- }
-};
-}
-}