|
|
@ -1,13 +1,14 @@ |
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <gp/pair.hpp>
|
|
|
|
#include <gp/bitops.hpp>
|
|
|
|
#include <gp/optional.hpp>
|
|
|
|
#include <gp/pair.hpp>
|
|
|
|
#include <gp/variant.hpp>
|
|
|
|
#include <gp/vector.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
namespace gp { |
|
|
|
enum class cbor_type { |
|
|
|
enum class cbor_type o">: uint8_t { |
|
|
|
uint = 0, |
|
|
|
nint = 1, |
|
|
|
bstr = 2, |
|
|
@ -18,7 +19,7 @@ namespace gp { |
|
|
|
oths = 7 |
|
|
|
}; |
|
|
|
|
|
|
|
enum class cbor_oths { |
|
|
|
enum class cbor_oths o">: 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<typename T> |
|
|
|
using cbor_composite = gp::fixed_variant< |
|
|
|
undefined_t, |
|
|
|
cbor_number, |
|
|
|
gp::buffer<std::byte>, |
|
|
|
bool, |
|
|
|
gp::vector<T>, |
|
|
|
gp::vector<gp::pair<T, T>>, |
|
|
|
gp::nullopt_t, |
|
|
|
undefined_t, |
|
|
|
cbor_floating_point |
|
|
|
>; |
|
|
|
|
|
|
@ -140,7 +144,6 @@ namespace gp { |
|
|
|
return *this; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto new_array() { |
|
|
|
return gp::vector<cbor_value>{alloc}; |
|
|
|
} |
|
|
@ -148,5 +151,88 @@ namespace gp { |
|
|
|
auto new_object() { |
|
|
|
return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc}; |
|
|
|
} |
|
|
|
|
|
|
|
static auto encode_length(buffer<std::byte> 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<gp::endian_wrapper<uint16_t, gp::endian::big>>())[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<gp::endian_wrapper<uint32_t, gp::endian::big>>())[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<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num.value; |
|
|
|
return dest.begin()+9; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
auto encode(buffer<std::byte> dest) { |
|
|
|
switch(contents.type()) { |
|
|
|
case cbor_composite<cbor_value>::alt<undefined_t>(): { |
|
|
|
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<cbor_value>::alt<cbor_number>(): { |
|
|
|
auto& ref = contents.value<cbor_number>(); |
|
|
|
return encode_length( |
|
|
|
dest, |
|
|
|
ref.is_negative() ? cbor_type::nint : cbor_type::uint, |
|
|
|
ref.value |
|
|
|
); |
|
|
|
} |
|
|
|
case cbor_composite<cbor_value>::alt<gp::buffer<std::byte>>(): { |
|
|
|
auto& ref = contents.value<gp::buffer<std::byte>>(); |
|
|
|
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<cbor_value>::alt<bool>(): { |
|
|
|
if(dest.size() < 1) return dest.begin(); |
|
|
|
if(contents.value<bool>()) |
|
|
|
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<cbor_value>::alt<gp::vector<cbor_value>>(): { |
|
|
|
|
|
|
|
} |
|
|
|
case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): { |
|
|
|
|
|
|
|
} |
|
|
|
case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): { |
|
|
|
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<cbor_value>::alt<cbor_floating_point>(): { |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
} |