summaryrefslogtreecommitdiff
path: root/modules/codec-json
diff options
context:
space:
mode:
authorClaudius "keldu" Holeksa <mail@keldu.de>2024-02-14 11:06:11 +0100
committerClaudius "keldu" Holeksa <mail@keldu.de>2024-02-14 11:06:11 +0100
commitd6380ea2911800882e1470e4ce1172bbeabf5dd2 (patch)
treea45e451d9f8c2e676a4f44e7f6e822e50893fb55 /modules/codec-json
parentd1d40903a582099762db04feeec451d7f0a617a8 (diff)
codec-json: Prettified tuple encoding
Diffstat (limited to 'modules/codec-json')
-rw-r--r--modules/codec-json/c++/json.hpp26
-rw-r--r--modules/codec-json/c++/json.tmpl.hpp120
-rw-r--r--modules/codec-json/tests/codec-json.cpp32
3 files changed, 124 insertions, 54 deletions
diff --git a/modules/codec-json/c++/json.hpp b/modules/codec-json/c++/json.hpp
index ad29acb..20342e3 100644
--- a/modules/codec-json/c++/json.hpp
+++ b/modules/codec-json/c++/json.hpp
@@ -59,6 +59,20 @@ public:
return buffer_.read(i);
}
};
+
+template<typename Encoding>
+struct codec_config;
+
+template<>
+struct codec_config<encode::Json> {
+ uint64_t depth = 16u;
+ uint64_t length = 4096u;
+ bool pretty = false;
+
+ bool is_within(uint64_t bytes, uint64_t d){
+ return bytes <= length && d <= depth;
+ }
+};
}
#include "json.tmpl.hpp"
@@ -70,14 +84,8 @@ namespace saw {
*/
template<typename Schema>
class codec<Schema, encode::Json> {
-public:
- struct config {
- size_t depth = 16;
- size_t length = 4096;
- bool pretty = false;
- };
private:
- config cfg_;
+ codec_config<encode::Json> cfg_;
public:
/**
* Default constructor
@@ -87,7 +95,7 @@ public:
/**
* Constructor
*/
- codec(config cfg__):cfg_{std::move(cfg__)}{}
+ codec(const codec_config<encode::Json>& cfg__):cfg_{cfg_}{}
SAW_FORBID_COPY(codec);
SAW_DEFAULT_MOVE(codec);
@@ -96,7 +104,7 @@ public:
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, FromEncoding>::encode(from_encode, buff_v);
+ auto eov = impl::json_encode<Schema, FromEncoding>::encode(from_encode, buff_v, 0, cfg_.pretty);
if(eov.is_error()){
return std::move(eov.get_error());
}
diff --git a/modules/codec-json/c++/json.tmpl.hpp b/modules/codec-json/c++/json.tmpl.hpp
index 11eba49..748f2c2 100644
--- a/modules/codec-json/c++/json.tmpl.hpp
+++ b/modules/codec-json/c++/json.tmpl.hpp
@@ -7,6 +7,34 @@
namespace saw {
namespace impl {
+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);
+ }
+ }
+
+ static error_or<void> print_pretty_indent(buffer& to, uint64_t depth){
+ {
+ auto eov = to.push(*reinterpret_cast<const uint8_t*>("\r\n"), 2);
+ if(!eov.template is_type<err::no_error>()){
+ return eov;
+ }
+ }
+ for(uint64_t ind = 0; ind < depth; ++ind){
+ auto eov_ele = to.push('\t');
+ if(!eov_ele.template is_type<err::no_error>()){
+ return eov_ele;
+ }
+ }
+ return void_t{};
+ }
+};
+
template<typename Schema, typename FromEncode>
class json_encode {
static_assert(always_false<Schema, FromEncode>, "This schema type is not being handled by the json encoding.");
@@ -16,7 +44,7 @@ template<typename T, size_t N, typename FromEncode>
struct json_encode<schema::Primitive<T,N>, FromEncode> {
using Schema = schema::Primitive<T,N>;
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t, bool) {
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);
@@ -49,7 +77,7 @@ template<typename FromEncode>
struct json_encode<schema::String, FromEncode> {
using Schema = schema::String;
- static error_or<void> encode(const data<schema::String, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<schema::String, FromEncode>& from, buffer& to, uint64_t, bool) {
{
auto err = to.push('"');
if(!err.template is_type<err::no_error>()){
@@ -78,11 +106,19 @@ struct json_encode<schema::Tuple<T...>, FromEncode> {
using Schema = schema::Tuple<T...>;
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, FromEncode>::encode(from.template get<i>(), to);
+ static error_or<void> encode_element(const data<schema::Tuple<T...>, FromEncode>& from, buffer& to, uint64_t depth, bool pretty){
+ if(pretty){
+ auto eov = json_helper::print_pretty_indent(to, depth);
+ if(eov.is_error()){
+ return eov;
+ }
+ }
+ {
+ auto eov = json_encode<typename parameter_pack_type<i, T...>::type, FromEncode>::encode(from.template get<i>(), to, depth, pretty);
- if(eov.is_error()){
- return eov;
+ if(eov.is_error()){
+ return eov;
+ }
}
if constexpr ( (i+1) < sizeof...(T)){
@@ -93,26 +129,31 @@ struct json_encode<schema::Tuple<T...>, FromEncode> {
}
}
{
- auto eov_ele = encode_element<i+1>(from, to);
+ auto eov_ele = encode_element<i+1>(from, to, depth, pretty);
if(eov_ele.is_error()){
return eov_ele;
}
}
-
-
}
return void_t{};
}
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty) {
{
+
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);
+ auto eov = encode_element<0>(from, to, depth+1u, pretty);
+ if(eov.is_error()){
+ return eov;
+ }
+ }
+ if(pretty){
+ auto eov = json_helper::print_pretty_indent(to, depth);
if(eov.is_error()){
return eov;
}
@@ -133,9 +174,9 @@ struct json_encode<schema::Array<T,D>, FromEncode> {
using Schema = schema::Array<T,D>;
template<size_t Level>
- static error_or<void> encode_level(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, D>& index){
+ static error_or<void> encode_level(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, D>& index, uint64_t depth, bool pretty){
if constexpr (Level == D){
- auto eov = json_encode<T, FromEncode>::encode(from.at(index), to);
+ auto eov = json_encode<T, FromEncode>::encode(from.at(index), to, depth, pretty);
if(eov.is_error()){
return eov;
}
@@ -155,7 +196,7 @@ struct json_encode<schema::Array<T,D>, FromEncode> {
}
{
index[Level] = i;
- auto eov = encode_level<Level+1>(from, to, index);
+ auto eov = encode_level<Level+1>(from, to, index, depth, pretty);
if(eov.is_error()){
return eov;
}
@@ -171,9 +212,9 @@ struct json_encode<schema::Array<T,D>, FromEncode> {
return void_t{};
}
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty) {
std::array<std::size_t, D> index;
- return encode_level<0>(from, to, index);
+ return encode_level<0>(from, to, index, depth, pretty);
}
};
@@ -181,8 +222,8 @@ template<typename T, size_t... D, typename FromEncode>
struct json_encode<schema::FixedArray<T,D...>, FromEncode> {
using Schema = schema::FixedArray<T,D...>;
- static error_or<void> encode_at(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, sizeof...(D)>& index){
- auto eov = json_encode<T, FromEncode>::encode(from.at(index), to);
+ static error_or<void> encode_at(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, sizeof...(D)>& index, uint64_t depth, bool pretty){
+ auto eov = json_encode<T, FromEncode>::encode(from.at(index), to, depth, pretty);
if(eov.is_error()){
return eov;
}
@@ -190,7 +231,7 @@ struct json_encode<schema::FixedArray<T,D...>, FromEncode> {
}
template<size_t Level, size_t Dim, size_t... DimPack>
- static error_or<void> encode_level(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, sizeof...(D)>& index){
+ static error_or<void> encode_level(const data<Schema, FromEncode>& from, buffer& to, std::array<std::size_t, sizeof...(D)>& index, uint64_t depth, bool pretty){
{
auto err = to.push('[');
if(!err.template is_type<err::no_error>()){
@@ -207,12 +248,12 @@ struct json_encode<schema::FixedArray<T,D...>, FromEncode> {
{
index[Level] = i;
if constexpr (sizeof...(DimPack) > 0){
- auto eov = encode_level<Level+1, DimPack...>(from, to, index);
+ auto eov = encode_level<Level+1, DimPack...>(from, to, index, depth, pretty);
if(eov.is_error()){
return eov;
}
}else{
- auto eov = encode_at(from,to,index);
+ auto eov = encode_at(from,to,index,depth,pretty);
if(eov.is_error()){
return eov;
}
@@ -228,10 +269,10 @@ struct json_encode<schema::FixedArray<T,D...>, FromEncode> {
return void_t{};
}
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty) {
if constexpr (sizeof...(D) > 0){
std::array<std::size_t, sizeof...(D)> index;
- return encode_level<0,D...>(from, to, index);
+ return encode_level<0,D...>(from, to, index, depth+1u, pretty);
}
return void_t{};
}
@@ -242,7 +283,7 @@ struct json_encode<schema::Struct<schema::Member<T,Key>...>, FromEncode> {
using Schema = schema::Struct<schema::Member<T,Key>...>;
template<size_t i>
- static error_or<void> encode_element(const data<Schema, FromEncode>& from, buffer& to){
+ static error_or<void> encode_element(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty){
// Encode the name
{
std::string_view view = parameter_key_pack_type<i, Key...>::literal.view();
@@ -268,7 +309,7 @@ struct json_encode<schema::Struct<schema::Member<T,Key>...>, FromEncode> {
}
// Encode the value
- auto eov = json_encode<typename parameter_pack_type<i, T...>::type, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to);
+ auto eov = json_encode<typename parameter_pack_type<i, T...>::type, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to, depth, pretty);
// Go to the next element
if constexpr ( (i+1) < sizeof...(T)){
@@ -279,7 +320,7 @@ struct json_encode<schema::Struct<schema::Member<T,Key>...>, FromEncode> {
}
}
{
- auto eov_ele = encode_element<i+1>(from, to);
+ auto eov_ele = encode_element<i+1>(from, to, depth, pretty);
if(eov_ele.is_error()){
return eov_ele;
}
@@ -290,7 +331,7 @@ struct json_encode<schema::Struct<schema::Member<T,Key>...>, FromEncode> {
return void_t{};
}
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty) {
{
auto err = to.push('{');
if(!err.template is_type<err::no_error>()){
@@ -298,7 +339,7 @@ struct json_encode<schema::Struct<schema::Member<T,Key>...>, FromEncode> {
}
}
if constexpr ( sizeof...(T) > 0 ){
- auto eov = encode_element<0>(from, to);
+ auto eov = encode_element<0>(from, to, depth, pretty);
if(eov.is_error()){
return eov;
}
@@ -319,7 +360,7 @@ struct json_encode<schema::Union<schema::Member<T,Key>...>, FromEncode> {
using Schema = schema::Union<schema::Member<T,Key>...>;
template<size_t i>
- static error_or<void> encode_element(const data<Schema, FromEncode>& from, buffer& to){
+ static error_or<void> encode_element(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty){
if(from.template holds_alternative<parameter_key_pack_type<i, Key...>::literal>()){
// Encode the name
{
@@ -346,12 +387,12 @@ struct json_encode<schema::Union<schema::Member<T,Key>...>, FromEncode> {
}
// Encode the value
- auto eov = json_encode<typename parameter_pack_type<i, T...>::type, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to);
+ auto eov = json_encode<typename parameter_pack_type<i, T...>::type, FromEncode>::encode(from.template get<parameter_key_pack_type<i, Key...>::literal>(), to, depth, pretty);
}
// Go to the next element
if constexpr ( (i+1) < sizeof...(T)){
{
- auto eov_ele = encode_element<i+1>(from, to);
+ auto eov_ele = encode_element<i+1>(from, to, depth, pretty);
if(eov_ele.is_error()){
return eov_ele;
}
@@ -362,7 +403,7 @@ struct json_encode<schema::Union<schema::Member<T,Key>...>, FromEncode> {
return void_t{};
}
- static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to) {
+ static error_or<void> encode(const data<Schema, FromEncode>& from, buffer& to, uint64_t depth, bool pretty) {
{
auto err = to.push('{');
if(!err.template is_type<err::no_error>()){
@@ -370,7 +411,7 @@ struct json_encode<schema::Union<schema::Member<T,Key>...>, FromEncode> {
}
}
if constexpr ( sizeof...(T) > 0 ){
- auto eov = encode_element<0>(from, to);
+ auto eov = encode_element<0>(from, to, depth, pretty);
if(eov.is_error()){
return eov;
}
@@ -386,18 +427,6 @@ struct json_encode<schema::Union<schema::Member<T,Key>...>, FromEncode> {
}
};
-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 ToDecode>
struct json_decode;
@@ -667,6 +696,7 @@ struct json_decode<schema::Tuple<T...>, ToDecode> {
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>();
}
diff --git a/modules/codec-json/tests/codec-json.cpp b/modules/codec-json/tests/codec-json.cpp
index 375d543..723e78c 100644
--- a/modules/codec-json/tests/codec-json.cpp
+++ b/modules/codec-json/tests/codec-json.cpp
@@ -352,4 +352,36 @@ SAW_TEST("Int64 read"){
typename native_data_type<schema::Int64>::type dec_val = -453;
SAW_EXPECT( dec_val == native_int.get(), std::string{"Value is not being encoded correctly. Encoded: "} + std::to_string(static_cast<int>(native_int.get())));
}
+
+SAW_TEST("Tuple Pretty Encode and Decode"){
+ using namespace saw;
+ data<schema::TestTuple, encode::Native> native_tup;
+ data<schema::TestTuple, encode::Json> json_tup;
+
+ auto& nat_zero = native_tup.template get<0>();
+ auto& nat_one = native_tup.template get<1>();
+
+ nat_zero.set("bar");
+ nat_one.set(34);
+
+ codec_config<encode::Json> json_config;
+ json_config.pretty = true;
+ codec<schema::TestTuple, encode::Json> json_codec{json_config};
+
+ error_or<void> eov = json_codec.encode(native_tup, json_tup);
+ SAW_EXPECT(eov.is_value(), "Encoding error");
+
+ std::string_view str_v = "[\r\n\t\"bar\",\r\n\t34\r\n]";
+ std::string enc_val = convert_to_string(json_tup.get_buffer());
+
+ SAW_EXPECT(enc_val == str_v, std::string{"Tuple not encoded correctly. Encoded: "} + enc_val + std::string{" Expected: "} + std::string{str_v});
+ native_tup = {};
+
+ eov = json_codec.decode(json_tup, native_tup);
+ SAW_EXPECT(eov.is_value(), "Decoding error");
+
+ SAW_EXPECT(native_tup.template get<0>() == "bar", "Invalid Value 0");
+ SAW_EXPECT(native_tup.template get<1>().get() == 34, "Invalid Value 1");
+
+}
}