diff --git a/include/gp/enveloppe/cbor.hpp b/include/gp/enveloppe/cbor.hpp index 95b79a4..41df107 100644 --- a/include/gp/enveloppe/cbor.hpp +++ b/include/gp/enveloppe/cbor.hpp @@ -1,13 +1,14 @@ #pragma once -#include +#include #include +#include #include #include namespace gp { - enum class cbor_type { + enum class cbor_type : uint8_t { uint = 0, nint = 1, bstr = 2, @@ -18,7 +19,7 @@ namespace gp { oths = 7 }; - enum class cbor_oths { + enum class cbor_oths : uint8_t { value_false = 20, value_true = 21, value_null = 22, @@ -55,16 +56,19 @@ namespace gp { signature = 55799 }; - using cbor_number = gp::fixed_variant< - int8_t, - uint8_t, - int16_t, - uint16_t, - int32_t, - uint32_t, - int64_t, - uint64_t - >; + struct cbor_number final { + bool sign; + uint64_t value; + + bool is_negative() { + return sign; + } + + cbor_number(int64_t v) + : sign{v < 0} + , value{uint64_t((sign ? -1 : 1) * v)} + {} + }; using cbor_floating_point = gp::fixed_variant< float, @@ -75,13 +79,13 @@ namespace gp { template using cbor_composite = gp::fixed_variant< + undefined_t, cbor_number, gp::buffer, bool, gp::vector, gp::vector>, gp::nullopt_t, - undefined_t, cbor_floating_point >; @@ -140,7 +144,6 @@ namespace gp { return *this; } - auto new_array() { return gp::vector{alloc}; } @@ -148,5 +151,88 @@ namespace gp { auto new_object() { return gp::vector>{alloc}; } + + static auto encode_length(buffer dest, cbor_type major, uint64_t value) { + auto num = value; + if(value <= 23) { + if(dest.size() < 1) return dest.begin(); + dest[0] = std::byte(((uint8_t)major << 5u) + value); + return dest.begin()+1; + } else if(value <= 255) { + if(dest.size() < 2) return dest.begin(); + dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte); + dest[1] = std::byte(value); + return dest.begin() + 2; + } else if(value <= 65535) { + if(dest.size() < 3) return dest.begin(); + dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word); + (dest.slice_start(3).slice_end(2).cast>())[0] = num.value; + return dest.begin()+3; + } else if(value <= 4294967295) { + if(dest.size() < 5) return dest.begin(); + dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword); + (dest.slice_start(5).slice_end(4).cast>())[0] = num.value; + return dest.begin()+5; + } else { + if(dest.size() < 9) return dest.begin(); + dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword); + (dest.slice_start(9).slice_end(8).cast>())[0] = num.value; + return dest.begin()+9; + } + } + + auto encode(buffer dest) { + switch(contents.type()) { + case cbor_composite::alt(): { + if(dest.size() < 1) return dest.begin(); + dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined); + return dest.begin()+1; + } + case cbor_composite::alt(): { + auto& ref = contents.value(); + return encode_length( + dest, + ref.is_negative() ? cbor_type::nint : cbor_type::uint, + ref.value + ); + } + case cbor_composite::alt>(): { + auto& ref = contents.value>(); + auto it = encode_length( + dest, + cbor_type::bstr, + ref.size() + ); + if(it == dest.begin()) return it; + + for(auto a : ref) { + *(it++) = a; + } + return it; + } + case cbor_composite::alt(): { + if(dest.size() < 1) return dest.begin(); + if(contents.value()) + dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true); + else + dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false); + return dest.begin()+1; + } + case cbor_composite::alt>(): { + + } + case cbor_composite::alt>>(): { + + } + case cbor_composite::alt(): { + if(dest.size() < 1) return dest.begin(); + dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null); + return dest.begin()+1; + } + case cbor_composite::alt(): { + + } + } + } }; } \ No newline at end of file diff --git a/include/gp/variant.hpp b/include/gp/variant.hpp index 6341fb1..749ff69 100644 --- a/include/gp/variant.hpp +++ b/include/gp/variant.hpp @@ -98,7 +98,7 @@ namespace gp{ } template - constexpr size_t alt() const { + constexpr static size_t alt() { return r_index_of::value; } diff --git a/tests/cbor_test.cpp b/tests/cbor_test.cpp index e85023f..414077d 100644 --- a/tests/cbor_test.cpp +++ b/tests/cbor_test.cpp @@ -12,11 +12,6 @@ struct cbor_test : public test_scaffold { virtual int run() { gp::array store; gp::arena alloc{&*store.begin(), store.size()}; - /*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;*/ using some_int = gp::fixed_variant; { @@ -58,6 +53,13 @@ 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"); } + { + 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; + } return 0; }