diff --git a/include/ircd/cbor/cbor.h b/include/ircd/cbor.h similarity index 57% rename from include/ircd/cbor/cbor.h rename to include/ircd/cbor.h index b3edbd3d5..b9a83981c 100644 --- a/include/ircd/cbor/cbor.h +++ b/include/ircd/cbor.h @@ -22,46 +22,11 @@ namespace ircd::cbor enum major :uint8_t; enum minor :uint8_t; - struct head; string_view reflect(const enum major &); - enum major major(const const_buffer &); + } -/// Item head. -/// -/// This object represents the head byte and any following-integer bytes under -/// its const_buffer. If the major type has a payload, it starts immediately -/// following the end of this object's buffer. The first byte of this object's -/// buffer is the leading head byte. This object's buffer will never be empty() -/// unless it's default-initialized (i.e not pointing at anything). -/// -/// This is used to query information about the item from the head data. -/// -struct ircd::cbor::head -:const_buffer -{ - static uint8_t major(const uint8_t &); // Major type - static uint8_t minor(const uint8_t &); // Minor type - static size_t length(const uint8_t &); // (1 + size(following())) - - // Member ops when buffer has >= 1 byte - const uint8_t &leading() const; // Reference the leading byte - enum major major() const; // major(leading()) - enum minor minor() const; // minor(leading()) - size_t length() const; // length(leading()) - - // Get bytes following leading byte based on major/minor - const_buffer following() const; - template const T &following() const; - - // Construct from at least first byte of item or more - head(const const_buffer &); - head() = default; - head(head &&) = default; - head(const head &) = default; -}; - /// RFC7049 Major type codes enum ircd::cbor::major :uint8_t diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index df80c2ab3..5d4f3c4a9 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -76,7 +76,7 @@ #include "color.h" #include "rfc1459.h" #include "json/json.h" -#include "cbor/cbor.h" +#include "cbor.h" #include "nacl.h" #include "ed25519.h" #include "openssl.h" diff --git a/ircd/cbor.cc b/ircd/cbor.cc index 379a1f676..ffcbbdc6e 100644 --- a/ircd/cbor.cc +++ b/ircd/cbor.cc @@ -8,114 +8,17 @@ // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. -/// Given a buffer of CBOR this function parses the head data and maintains -/// a const_buffer span of the head. The span includes the leading head byte -/// and one or more integer bytes following the leading byte. If the major -/// type found in this head has a data payload which is not a following-integer -/// then that data starts directly after this head buffer ends. -/// -/// The argument buffer must be at least one byte and must at least cover the -/// following-integer bytes (and can also be as large as possible). -/// -ircd::cbor::head::head(const const_buffer &buf) -:const_buffer{[&buf] +namespace ircd::cbor { - if(unlikely(size(buf) < sizeof(uint8_t))) - throw buffer_underrun - { - "Item buffer is too small to contain a header" - }; - - const uint8_t &leading - { - *reinterpret_cast(data(buf)) - }; - - return const_buffer - { - data(buf), length(leading) - }; -}()} -{ - if(unlikely(size(*this) > size(buf))) - throw buffer_underrun - { - "Item buffer is too small to contain full header" - }; + static uint8_t _major(const uint8_t &); // Major type + static uint8_t _minor(const uint8_t &); // Minor type + static size_t _length(const uint8_t &); // (1 + size(following())) } -/// Pun a reference to the integer contained by the bytes following the head. -/// If there are no bytes following the head because the integer is contained -/// as bits packed into the leading head byte, this function will throw. -/// -template -const T & -ircd::cbor::head::following() -const -{ - if(unlikely(size(following()) < sizeof(T))) - throw buffer_underrun - { - "Buffer following header is too small (%zu) for type requiring %zu", - size(following()), - sizeof(T) - }; - - return *reinterpret_cast(data(following())); -} - -/// Return buffer spanning the integer bytes following this head. This may be -/// an empty buffer if the integer byte is packed into bits of the leading -/// byte (denoted by minor()). -ircd::const_buffer -ircd::cbor::head::following() -const -{ - return { data(*this) + 1, length() - 1 }; -} - -/// Extract the length of the head from the buffer (requires 1 byte of buffer) size_t -ircd::cbor::head::length() -const +ircd::cbor::_length(const uint8_t &a) { - return length(leading()); -} - -/// Extract the minor type from the reference to the leading byte in the head. -enum ircd::cbor::minor -ircd::cbor::head::minor() -const -{ - return static_cast(minor(leading())); -} - -/// Extract the major type from the reference to the leading byte in the head. -enum ircd::cbor::major -ircd::cbor::head::major() -const -{ - return static_cast(major(leading())); -} - -/// Reference the leading byte of the head. -const uint8_t & -ircd::cbor::head::leading() -const -{ - assert(size(*this) >= sizeof(uint8_t)); - return *reinterpret_cast(data(*this)); -} - -/// Extract length of head from leading head byte (arg); this is the length of -/// the integer following the leading head byte plus the one leading head -/// byte. This length covers all bytes which come before item payload bytes -/// (when such a payload exists). If this length is 1 then no integer bytes -/// are following the leading head byte. The length/returned value is never 0. -size_t -ircd::cbor::head::length(const uint8_t &a) -{ - switch(major(a)) + switch(_major(a)) { case POSITIVE: case NEGATIVE: @@ -125,7 +28,7 @@ ircd::cbor::head::length(const uint8_t &a) case OBJECT: case TAG: { - if(minor(a) > 23) switch(minor(a)) + if(_minor(a) > 23) switch(_minor(a)) { case minor::U8: return 2; case minor::U16: return 3; @@ -133,7 +36,8 @@ ircd::cbor::head::length(const uint8_t &a) case minor::U64: return 9; default: throw type_error { - "Unknown minor type (%u); length of header unknown", minor(a) + "Unknown minor type (%u); length of header unknown", + _minor(a) }; } else return 1; @@ -141,7 +45,7 @@ ircd::cbor::head::length(const uint8_t &a) case PRIMITIVE: { - if(minor(a) > 23) switch(minor(a)) + if(_minor(a) > 23) switch(_minor(a)) { case FALSE: case TRUE: @@ -152,7 +56,8 @@ ircd::cbor::head::length(const uint8_t &a) case minor::F64: return 9; default: throw type_error { - "Unknown primitive minor type (%u); length of header unknown", minor(a) + "Unknown primitive minor type (%u); length of header unknown", + _minor(a) }; } else return 1; @@ -167,16 +72,15 @@ ircd::cbor::head::length(const uint8_t &a) /// Extract major type from leading head byte (arg) uint8_t -ircd::cbor::head::major(const uint8_t &a) +ircd::cbor::_major(const uint8_t &a) { // shift for higher 3 bits only - static const auto shift(5); - return a >> shift; + return a >> 5; } /// Extract minor type from leading head byte (arg) uint8_t -ircd::cbor::head::minor(const uint8_t &a) +ircd::cbor::_minor(const uint8_t &a) { // mask of lower 5 bits only static const uint8_t mask @@ -187,17 +91,6 @@ ircd::cbor::head::minor(const uint8_t &a) return a & mask; } -// -// cbor.h -// - -enum ircd::cbor::major -ircd::cbor::major(const const_buffer &buf) -{ - const head head(buf); - return head.major(); -} - ircd::string_view ircd::cbor::reflect(const enum major &major) {