diff --git a/include/gp/ipc/envelope/cbor.hpp b/include/gp/ipc/envelope/cbor.hpp index 80099af..dddcf50 100644 --- a/include/gp/ipc/envelope/cbor.hpp +++ b/include/gp/ipc/envelope/cbor.hpp @@ -7,6 +7,8 @@ #include #include +#include + // TODO: Rewrite in a more ORM-like way // TODO: Implement some bignum for support @@ -113,12 +115,6 @@ namespace gp { - - template - vector& push_as_cbor(vector&, T); - - template - vector& push_as_cbor(vector&, T&); inline vector& push_integer_with_header_as_cbor(vector& src, uint8_t header, uint64_t value) { auto norm_v = (value<0) ? -value : value; @@ -156,8 +152,8 @@ namespace gp { * @param value the value to push, can be signed * @return vector& the same reference that was received for the source */ - template<> - inline vector& push_as_cbor(vector& src, int64_t& value) { + template + inline vector& push_as_cbor(vector& src, T value) { uint8_t sign = (value<0) ? 0b00100000 : 0; auto norm_v = (value<0) ? -value : value; return push_integer_with_header_as_cbor(src, sign, norm_v); @@ -170,33 +166,29 @@ namespace gp { * @param value the value to push, cannot be signed * @return vector& the same reference that was received for the source */ - template<> - inline vector& push_as_cbor(vector& src, uint64_t& value) { + template + inline vector& push_as_cbor(vector& src, T value) { return push_integer_with_header_as_cbor(src, 0, value); } - template<> - inline vector& push_as_cbor(vector& src, std::nullptr_t) { + inline vector& push_as_cbor(vector& src, std::nullptr_t) { src.push_back(0b11110110); return src; } struct cbor_undefined{}; - template<> - inline vector& push_as_cbor(vector& src, cbor_undefined) { + inline vector& push_as_cbor(vector& src, cbor_undefined) { src.push_back(0b11110111); return src; } - template<> - inline vector& push_as_cbor(vector& src, bool value) { + inline vector& push_as_cbor(vector& src, bool value) { src.push_back(0b11110100+(value ? 1 : 0)); return src; } - template<> - inline vector& push_as_cbor>(vector& src, gp::buffer value) { + inline vector& push_as_cbor(vector& src, gp::buffer value) { push_integer_with_header_as_cbor(src, (uint8_t)0b01000000, value.size()); for(auto byte : value) { src.push_back(byte); @@ -212,20 +204,24 @@ namespace gp { size_t size; }; - template<> - inline vector& push_as_cbor(vector& src, cbor_array_initiator value) { + inline vector& push_as_cbor(vector& src, cbor_array_initiator value) { return push_integer_with_header_as_cbor(src, (uint8_t)0b10000000, value.size); } - template<> - inline vector& push_as_cbor(vector& src, cbor_associative_array_initiator value) { + inline vector& push_as_cbor(vector& src, cbor_associative_array_initiator value) { return push_integer_with_header_as_cbor(src, (uint8_t)0b10100000, value.size); } + template + inline vector& push_as_cbor(vector& src, gp::pair value) { + push_as_cbor(src,value.first); + return push_as_cbor(src,value.second); + } + template inline vector& push_as_cbor(vector& src, gp::pair& value) { - push_as_cbor(src,value.first); - return push_as_cbor(src,value.second); + push_as_cbor(src,value.first); + return push_as_cbor(src,value.second); } struct cbor_tag_initiator { @@ -235,15 +231,14 @@ namespace gp { }; }; - template<> - inline vector& push_as_cbor(vector& src, cbor_tag_initiator value) { + inline vector& push_as_cbor(vector& src, cbor_tag_initiator value) { return push_integer_with_header_as_cbor(src, (uint8_t)0b11000000, value.as_integer); } using parsing_state = gp::buffer; template - gp::pair, parsing_state> read_cbor(parsing_state state); + gp::pair, parsing_state> read_cbor(parsing_state state, gp::allocator&); inline gp::pair, parsing_state> pull_arbitrary_integer_from_cbor(parsing_state state) { auto local = (uint8_t)0b00011111 & (uint8_t)*state.begin(); @@ -258,21 +253,21 @@ namespace gp { case cbor_oths::word: { if(state.size() < 3) return {nullopt, state}; return { - uint16_t(*(state.slice_start(3).slice_end(2).cast>().begin().data)), + uint16_t(*(state.slice_start(3).slice_end(2).cast>().begin())), {state.begin()+3, state.end()} }; } case cbor_oths::dword: { if(state.size() < 5) return {nullopt, state}; return { - uint32_t(*(state.slice_start(5).slice_end(4).cast>().begin().data)), + uint32_t(*(state.slice_start(5).slice_end(4).cast>().begin())), {state.begin()+5, state.end()} }; } case cbor_oths::qword: { if(state.size() < 9) return {nullopt, state}; return { - uint64_t(*(state.slice_start(9).slice_end(8).cast>().begin().data)), + uint64_t(*(state.slice_start(9).slice_end(8).cast>().begin())), {state.begin()+9, state.end()} }; } @@ -283,8 +278,9 @@ namespace gp { } } - template<> - inline gp::pair, parsing_state> read_cbor(parsing_state state) { + template + inline gp::pair, parsing_state> read_cbor(parsing_state state, gp::allocator&) { + // TODO: Handling of over and underflow if(state.size()) return {nullopt, state}; auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); @@ -309,30 +305,153 @@ namespace gp { template<> - inline gp::pair, parsing_state> read_cbor(parsing_state state) { + inline gp::pair, parsing_state> read_cbor(parsing_state state, gp::allocator&) { if(state.size()) return {nullopt, state}; auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); switch(type) { - case cbor_type::uint: + case cbor_type::tags: { auto[value, new_state] = pull_arbitrary_integer_from_cbor(state); - if(value.has_value()) return {value.value(), new_state}; + if(value.has_value()) return {cbor_tag_initiator{.as_integer = value.value()}, new_state}; break; } - case cbor_type::nint: + default: break; + } + return {nullopt, state}; + } + + template<> + inline gp::pair>, parsing_state> read_cbor>(parsing_state state, gp::allocator& alloc) { + if(state.size()) return {nullopt, state}; + auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); + + switch(type) { + case cbor_type::bstr: { - auto[value, new_state] = pull_arbitrary_integer_from_cbor(state); - if( - value.has_value() - && value.value() < (uint64_t)std::numeric_limits::max() - ) { - return {-value.value(), new_state}; + const auto[size, new_state] = pull_arbitrary_integer_from_cbor(state); + if(!size.has_value()) break; + if(new_state.size() return_value{alloc}; + if(!return_value.reserve(size.value())) break; + auto end_it = new_state.begin() + size.value(); + for(auto it = new_state.begin(); it != end_it; it++) { + return_value.push_back(*it); } + return {optional>(gp::move(return_value)), parsing_state(new_state.begin() + size.value(), new_state.end())}; break; } default: break; } return {nullopt, state}; } -} \ No newline at end of file + + template<> + inline gp::pair, parsing_state> read_cbor(parsing_state state, gp::allocator& alloc) { + if(state.size()) return {nullopt, state}; + auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); + + switch(type) { + case cbor_type::oths: + { + const auto[value, new_state] = pull_arbitrary_integer_from_cbor(state); + if(!value.has_value()) break; + if(new_state.size() return_value{alloc}; + if(value.value() == 22) + { + return {optional(nullptr), parsing_state(new_state.begin()+1, new_state.end())}; + } + break; + } + default: break; + } + return {nullopt, state}; + } + + template<> + inline gp::pair, parsing_state> read_cbor(parsing_state state, gp::allocator& alloc) { + if(state.size()) return {nullopt, state}; + auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); + + switch(type) { + case cbor_type::oths: + { + const auto[value, new_state] = pull_arbitrary_integer_from_cbor(state); + if(!value.has_value()) break; + if(new_state.size() return_value{alloc}; + if(value.value() == 23) + { + return {optional(cbor_undefined{}), parsing_state(new_state.begin()+1, new_state.end())}; + } + break; + } + default: break; + } + return {nullopt, state}; + } + + /** + * @brief + * + * @param state + * @param callback a callback that returns a new parsing state for every element read. It should follow the heredescribed signature: parsing_state(parsing_state, gp::allocator&) + * @param count_callback a callback that is used to check if the process should proceed given a count of elements in the list. It should follow the heredescribed signature: bool(uint64_t) + * @param alloc + */ + template + inline parsing_state read_cbor_array(parsing_state state, gp::allocator& alloc, applier_cb callback, counter_cb count_callback = [](uint64_t) -> bool {return true;}) { + if(state.size()) return state; + auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); + + switch(type) { + case cbor_type::list: + { + const auto[size, new_state] = pull_arbitrary_integer_from_cbor(state); + if(!size.has_value()) return state; + if(new_state.size() + inline parsing_state read_cbor_kv_list(parsing_state state, gp::allocator& alloc, applier_cb callback, counter_cb count_callback = [](uint64_t) -> bool {return true;}) { + if(!state.size()) return state; + auto type = cbor_type(((uint8_t)0b11100000 & (uint8_t)*state.begin()) >> 5); + + switch(type) { + case cbor_type::hmap: + { + const auto[size, new_state] = pull_arbitrary_integer_from_cbor(state); + if(!size.has_value()) return state; + if(!count_callback(size.value()))return state; + parsing_state forward = new_state; + for(auto idx = 0ull; idx != size.value(); idx++) { + if(forward.size() < 2ull) return state; + forward = callback(forward, alloc); + forward = callback(forward, alloc); + } + return forward; + } + default: return state; + } + } +} + diff --git a/tests/cbor_test.cpp b/tests/cbor_test.cpp index 64ce22d..175ee77 100644 --- a/tests/cbor_test.cpp +++ b/tests/cbor_test.cpp @@ -5,15 +5,20 @@ #include #include "test_scaffold.h" -struct cbor_test : public test_scaffold { - cbor_test() { - name = __FILE__ ":1"; +#include +#include + +struct generic_cbor_test : public test_scaffold { + std::unique_ptr> store = std::make_unique>(); + gp::arena alloc{&*store->begin(), store->size()}; +}; + +struct cbor_test1 : public generic_cbor_test { + cbor_test1() { + name = __FILE__ ":" "##1"; } virtual int run() { - auto store = std::make_unique>(); - gp::arena alloc{&*store->begin(), store->size()}; - using some_int = gp::fixed_variant; { some_int a{16}; @@ -21,18 +26,51 @@ struct cbor_test : public test_scaffold { b = a; gp_config::assertion(b.is_a(), "b got wrong type assigned"); } + return 0; + } +}; + +struct cbor_test2 : public generic_cbor_test { + cbor_test2() { + name = __FILE__ ":" "##2"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { some_int a{16u}; some_int b = a; gp_config::assertion(b.is_a(), "b got wrong type assigned"); gp_config::assertion(b.value() == 16, "b got wrong value assigned"); } + return 0; + } +}; + +struct cbor_test3 : public generic_cbor_test { + cbor_test3() { + name = __FILE__ ":" "##3"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { some_int a{16u}; some_int b = gp::move(a); gp_config::assertion(b.is_a(), "b got wrong type assigned"); gp_config::assertion(b.value() == 16, "b got wrong value assigned"); } + return 0; + } +}; + +struct cbor_test4 : public generic_cbor_test { + cbor_test4() { + name = __FILE__ ":" "##4"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { some_int a{16u}; some_int b; @@ -40,6 +78,17 @@ struct cbor_test : public test_scaffold { gp_config::assertion(b.is_a(), "b got wrong type assigned"); gp_config::assertion(b.value() == 16, "b got wrong value assigned"); } + return 0; + } +}; + +struct cbor_test5 : public generic_cbor_test { + cbor_test5() { + name = __FILE__ ":" "##5"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { some_int a{16u}; some_int b; @@ -47,6 +96,17 @@ struct cbor_test : public test_scaffold { gp_config::assertion(b.is_a(), "b got wrong type assigned"); gp_config::assertion(b.value() == 16, "b got wrong value assigned"); } + return 0; + } +}; + +struct cbor_test6 : public generic_cbor_test { + cbor_test6() { + name = __FILE__ ":" "##6"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { gp::vector vec{alloc}; vec.emplace_back(12u); @@ -54,292 +114,500 @@ struct cbor_test : public test_scaffold { gp_config::assertion(vec[0].is_a(), "vec0 got wrong type assigned"); gp_config::assertion(vec[1].is_a(), "vec1 got wrong type assigned"); } - return 0; } }; -append_test dummy_pg5zhr8bv(new cbor_test{}); +struct cbor_test7 : public generic_cbor_test { + cbor_test7() { + name = __FILE__ ":" "##7"; + } + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + + gp::push_as_cbor(serialized, gp::cbor_associative_array_initiator{2}); + gp::push_as_cbor(serialized, gp::make_pair(uint64_t(12), int64_t(-98))); + gp::push_as_cbor(serialized, gp::make_pair(uint64_t(13), int64_t(98))); + + log_segment("serialized[0]", std::to_string((unsigned char)serialized[0]).c_str()); + log_segment("serialized[1]", std::to_string((unsigned char)serialized[1]).c_str()); + log_segment("serialized[2]", std::to_string((unsigned char)serialized[2]).c_str()); + log_segment("serialized[3]", std::to_string((unsigned char)serialized[3]).c_str()); + log_segment("serialized[4]", std::to_string((unsigned char)serialized[4]).c_str()); + log_segment("serialized[5]", std::to_string((unsigned char)serialized[5]).c_str()); + log_segment("serialized[6]", std::to_string((unsigned char)serialized[6]).c_str()); + + gp::array serialized_manual{ + char(0b10100010), + char(0b00001100), + char(0b00111000), char(98), + char(0b00001101), + char(0b00011000), char(98) + }; + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode: wrong output size"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } + + auto state = serialized_manual.as_buffer(); + size_t count = 0; + auto count_handler = [](size_t size){ + { + std::bitset size_bits{size}; + std::stringstream v; + v << size_bits; + log_segment("size bits", v.str().c_str()); + } + { + std::bitset size_bits{-size}; + std::stringstream v; + v << size_bits; + log_segment("-size bits", v.str().c_str()); + } + { + log_segment("-size value", std::to_string((size_t)-size).c_str()); + } + gp_config::assertion(size == 2, "could not decode the correct size"); + return true; + }; -/* - TODO: REWRITE THOSE BAD BOIS + auto callback_handler = [&count](gp::parsing_state state, gp::allocator& alloc) { + count++; + switch(count-1) { + case 0: { + auto [value, new_state] = gp::read_cbor(state, alloc); + gp_config::assertion(value.has_value(), "could not encode value"); + gp_config::assertion(value.value() == 12, "could not encode the correct size"); + return new_state; + } + case 1:{ + auto [value, new_state] = gp::read_cbor(state, alloc); + gp_config::assertion(value.has_value(), "could not encode value"); + gp_config::assertion(value.value() == -98, "could not encode the correct size"); + return new_state; + } + case 2:{ + auto [value, new_state] = gp::read_cbor(state, alloc); + gp_config::assertion(value.has_value(), "could not encode value"); + gp_config::assertion(value.value() == 13, "could not encode the correct size"); + return new_state; + } + case 3:{ + auto [value, new_state] = gp::read_cbor(state, alloc); + gp_config::assertion(value.has_value(), "could not encode value"); + gp_config::assertion(value.value() == 98, "could not encode the correct size"); + return new_state; + } + default: return state; + } + }; + auto new_state = read_cbor_kv_list( + state, + alloc, + callback_handler, + count_handler + ); + gp_config::assertion(state.size() > new_state.size(), "reading succeeded"); + gp_config::assertion(new_state.size() == 0, "something is left in the string"); + } + return 0; + } +}; +struct cbor_test8 : public generic_cbor_test { + cbor_test8() { + name = __FILE__ ":" "##8"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { - gp::cbor_value data{alloc}; - auto gen = data.new_object(); - gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(12), alloc}, gp::cbor_value{int32_t(-98), alloc})); - gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(13), alloc}, gp::cbor_value{uint32_t(98), alloc})); - data = gen; - - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b10100010), - std::byte(0b00001100), - std::byte(0b00111000), std::byte(98), - std::byte(0b00001101), - std::byte(0b00011000), std::byte(98) + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(1) }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, 1); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode (wrong size)"); + gp_config::assertion(serialized[0] == serialized_manual[0], "data did not encode correctly"); - gp::fill(serialized,(std::byte)0); + auto [value, new_state] = gp::read_cbor(serialized.as_buffer(), alloc); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(value.has_value(), "could not redecode"); + gp_config::assertion(value.value() == 1, "data did not serialize correctly: wrong value decoded"); } - { - gp::cbor_value data{alloc}; - data = gp::cbor_number(1); + return 0; + } + +}; + +struct cbor_test9 : public generic_cbor_test { + cbor_test9() { + name = __FILE__ ":" "##9"; + } - gp::array serialized; - gp::array serialized_manual{ - std::byte(1) + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b00011001), + char(0b00000100), + char(0b00000000) }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, 1024); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized_manual.size() == serialized.size(), "could not encode"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } - gp::fill(serialized,(std::byte)0); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not decode"); + gp_config::assertion(value.value() == 1024, "data did not decode correctly"); + } - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + return 0; + } + +}; - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } - { - gp::cbor_value data{alloc}; - data = bool(false); +struct cbor_test10 : public generic_cbor_test { + cbor_test10() { + name = __FILE__ ":" "##10"; + } - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b11100000+20) + virtual int run() { + using some_int = gp::fixed_variant; + + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b00011010), + char(0xAA), + char(0xBB), + char(0xCC), + char(0xDD) }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, 0xAABBCCDD); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized_manual.size() == serialized.size(), "could not encode"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } - gp::fill(serialized,(std::byte)0); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not decode"); + gp_config::assertion(value.value() == 0xAABBCCDD, "data did not decode correctly"); + } - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + return 0; + } + +}; - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } - { - gp::cbor_value data{alloc}; - data = bool(true); +struct cbor_test11 : public generic_cbor_test { + cbor_test11() { + name = __FILE__ ":" "##11"; + } - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b11100000+21) + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b00011011), + char(0xAA), + char(0xBB), + char(0xCC), + char(0xDD), + char(0xEE), + char(0xFF), + char(0x00), + char(0x11) }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, 0xAABBCCDDEEFF0011ull); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized_manual.size() == serialized.size(), "could not encode"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } - gp::fill(serialized,(std::byte)0); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not decode"); + gp_config::assertion(value.value() == 0xAABBCCDDEEFF0011ull, "data did not decode correctly"); + } - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + return 0; + } + +}; - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } - { - gp::cbor_value data{gp::nullopt, alloc}; +struct cbor_test12 : public generic_cbor_test { + cbor_test12() { + name = __FILE__ ":" "##12"; + } - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b11100000+22) + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b11100000+22) }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, nullptr); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode"); + gp_config::assertion(serialized[0] == serialized_manual[0], "data did not serialize correctly"); - gp::fill(serialized,(std::byte)0); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); - - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(value.has_value(), "could not encode"); + gp_config::assertion(value.value() == nullptr, "data did not decode correctly"); } - { - gp::cbor_value data{alloc}; - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b11100000+23) - }; + return 0; + } + +}; - auto ret_it = data.encode(serialized.as_buffer()); +struct cbor_test13 : public generic_cbor_test { + cbor_test13() { + name = __FILE__ ":" "##13"; + } - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b11100000+21) + }; - gp::fill(serialized,(std::byte)0); + gp::push_as_cbor(serialized, true); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode"); + gp_config::assertion(serialized[0] == serialized_manual[0], "data did not serialize correctly"); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not encode"); + gp_config::assertion(value.value() == true, "data did not decode correctly"); } - { - gp::cbor_value data{alloc}; - data = gp::cbor_number(128); - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b00011000), - std::byte(0b10000000) - }; + return 0; + } + +}; - auto ret_it = data.encode(serialized.as_buffer()); +struct cbor_test14 : public generic_cbor_test { + cbor_test14() { + name = __FILE__ ":" "##14"; + } - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b11100000+20) + }; - gp::fill(serialized,(std::byte)0); + gp::push_as_cbor(serialized, false); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode"); + gp_config::assertion(serialized[0] == serialized_manual[0], "data did not serialize correctly"); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not encode"); + gp_config::assertion(value.value() == false, "data did not decode correctly"); } - { - gp::cbor_value data{alloc}; - data = gp::cbor_number(1024); - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b00011001), - std::byte(0b00000100), - std::byte(0b00000000) - }; + return 0; + } + +}; - auto ret_it = data.encode(serialized.as_buffer()); +struct cbor_test15 : public generic_cbor_test { + cbor_test15() { + name = __FILE__ ":" "##15"; + } - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b11100000+24) + }; - gp::fill(serialized,(std::byte)0); + gp::push_as_cbor(serialized, gp::cbor_undefined{}); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode"); + gp_config::assertion(serialized[0] == serialized_manual[0], "data did not serialize correctly"); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + auto [value, state] = gp::read_cbor(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not encode"); } + + return 0; + } + +}; + +struct cbor_test16 : public generic_cbor_test { + cbor_test16() { + name = __FILE__ ":" "##16"; + } + + virtual int run() { + using some_int = gp::fixed_variant; { - gp::cbor_value data{alloc}; - data = gp::cbor_number(0xAABBCCDDu); + gp::vector str{alloc}; + str.reserve(5); + for(auto a : {'h', 'e', 'l', 'l', 'o'}) + str.push_back((char)a); + - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b00011010), - std::byte(0xAA), - std::byte(0xBB), - std::byte(0xCC), - std::byte(0xDD) + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o') }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, str.as_buffer()); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + gp_config::assertion(serialized.size() != serialized_manual.size(), "could not encode"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } - gp::fill(serialized,(std::byte)0); + auto [value, state] = gp::read_cbor>(serialized.as_buffer(), alloc); + + gp_config::assertion(value.has_value(), "could not decode"); + gp_config::assertion(value.value() == str, "data did not decode correctly"); + } - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); + return 0; + } - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } - { - gp::cbor_value data{alloc}; - data = gp::cbor_number(false, 0xAABBCCDDEEFF0011ull); +}; - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b00011011), - std::byte(0xAA), - std::byte(0xBB), - std::byte(0xCC), - std::byte(0xDD), - std::byte(0xEE), - std::byte(0xFF), - std::byte(0x00), - std::byte(0x11) +struct cbor_test17 : public generic_cbor_test { + cbor_test17() { + name = __FILE__ ":" "##17"; + } + + virtual int run() { + using some_int = gp::fixed_variant; + { + gp::vector str{alloc}; + str.reserve(5); + for(auto a : {'h', 'e', 'l', 'l', 'o'}) + str.push_back((char)a); + + gp::vector serialized(alloc); + gp::array serialized_manual{ + char(0b10000101), + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o'), + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o'), + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o'), + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o'), + char(0b01000101), + char('h'), + char('e'), + char('l'), + char('l'), + char('o') }; - auto ret_it = data.encode(serialized.as_buffer()); + gp::push_as_cbor(serialized, gp::cbor_array_initiator{5}); + gp::repeat(5, + [&](){ + gp::push_as_cbor(serialized, str.as_buffer()); + } + ); + + gp_config::assertion(serialized.size() == serialized_manual.size(), "could not encode"); + for(size_t idx = 0; idx < serialized_manual.size(); idx++) { + gp_config::assertion(serialized[idx] == serialized_manual[idx], "data did not serialize correctly"); + } + } - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); + return 0; + } +}; - gp::fill(serialized,(std::byte)0); +append_test dummy_pg5zhr84bv(new cbor_test1{}); +append_test dummy_pg5zdhr8bv(new cbor_test2{}); +append_test dummy_pg5zhrf8bv(new cbor_test3{}); +append_test dummy_pg5zhdr8bv(new cbor_test4{}); +append_test dummy_pg5zghr8bv(new cbor_test5{}); +append_test dummy_pg5zhfr8bv(new cbor_test6{}); +append_test dummy_pg5zhrs8bv(new cbor_test7{}); +append_test dummy_pg5zhrj8bv(new cbor_test8{}); +append_test dummy_pg5zhrh8bv(new cbor_test9{}); +append_test dummy_pg5zhrz8bv(new cbor_test10{}); +append_test dummy_pg5zhrg8bv(new cbor_test11{}); +append_test dummy_pg5zher8bv(new cbor_test12{}); +append_test dummy_pg5zhr8rbv(new cbor_test13{}); +append_test dummy_pg5zzhr8bv(new cbor_test14{}); +append_test dummy_p78shrg8bv(new cbor_test15{}); +append_test dummy_p4sddr8rbv(new cbor_test16{}); +append_test dummy_pg5zzdjobv(new cbor_test17{}); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } - { - gp::cbor_value data{alloc}; - data = gp::cbor_number(true, 0xAABBCCDDEEFF0011ull); +/* + TODO: REWRITE THOSE BAD BOIS - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b00111011), - std::byte(0xAA), - std::byte(0xBB), - std::byte(0xCC), - std::byte(0xDD), - std::byte(0xEE), - std::byte(0xFF), - std::byte(0x00), - std::byte(0x11) - }; - auto ret_it = data.encode(serialized.as_buffer()); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - gp::fill(serialized,(std::byte)0); - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } { gp::cbor_value data{alloc}; data = gp::cbor_floating_point(128.5f); @@ -396,37 +664,6 @@ append_test dummy_pg5zhr8bv(new cbor_test{}); gp_config::assertion(serialized.begin() != ret_it, "could not encode"); gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); } - { - gp::vector str{alloc}; - str.reserve(5); - for(auto a : {'h', 'e', 'l', 'l', 'o'}) - str.push_back((std::byte)a); - gp::cbor_value data{alloc}; - data = str; - - gp::array serialized; - gp::array serialized_manual{ - std::byte(0b01000101), - std::byte('h'), - std::byte('e'), - std::byte('l'), - std::byte('l'), - std::byte('o') - }; - - auto ret_it = data.encode(serialized.as_buffer()); - - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - - gp::fill(serialized,(std::byte)0); - - auto decoded = gp::cbor_value::decode(alloc, serialized_manual.as_buffer()); - ret_it = decoded.first.encode(serialized.as_buffer()); - - gp_config::assertion(serialized.begin() != ret_it, "could not encode"); - gp_config::assertion(serialized == serialized_manual, "data did not serialize correctly"); - } { gp::vector str{alloc}; str.reserve(5);