189#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
190#define __STDC_WANT_IEC_60559_TYPES_EXT__
204#include <string_view>
206#include <type_traits>
212#if (defined(FLT16_MIN) || defined(FLT16_MIN)) && !defined(NO_FLOAT16)
213#define CBOR_HALF_SUPPORT
216#if defined(CBOR_HALF_SUPPORT)
217typedef _Float16 half;
248 constexpr Major getMajor(uint8_t initial) {
return Major(initial >> 5); }
249 constexpr uint8_t setMajor(uint8_t initial,
Major major)
251 return static_cast<uint8_t
>(
252 (initial & ~(~0 << 5)) |
253 static_cast<uint8_t
>(major) << 5);
264 FourByteFollows = 26,
265 EightByteFollows = 27,
271 constexpr uint8_t EMBEDDED_MIN =
static_cast<uint8_t
>(Minor::EmbeddedFirst);
272 constexpr uint8_t EMBEDDED_MAX =
static_cast<uint8_t
>(Minor::EmbeddedLast);
273 constexpr Minor getMinor(uint8_t initial) {
return Minor(initial & ((1 << 5) - 1)); }
274 constexpr uint8_t setMinor(uint8_t initial,
Minor minor)
276 return static_cast<uint8_t
>(
277 (initial & (~0 << 5)) |
278 static_cast<uint8_t
>(minor));
280 constexpr uint8_t initialByte(
Major major,
Minor minor)
282 return setMinor(setMajor(0, major), minor);
284 consteval Minor minorFromSizeOf(
const size_t bytes)
288 bytes == 2 ? Minor::TwoByteFollows :
289 bytes == 4 ? Minor::FourByteFollows :
290 Minor::EightByteFollows;
296 Unassigned0First = 0,
297 Unassigned0Last = 19,
304 Unassigned1First = 32,
305 Unassigned1Last = 255,
311 template<
typename T,
typename Placeholder>
314 template<
typename Placeholder>
315 struct WrapVoid<void, Placeholder>
317 using T = Placeholder;
319 template<
typename Fn,
typename Tuple>
320 WrapVoid(Fn && fn, Tuple && args)
322 std::apply(std::forward<Fn>(fn), std::forward<Tuple>(args));
326 template<
typename U,
typename Placeholder>
requires (!std::same_as<U, void>)
327 struct WrapVoid<U, Placeholder>
331 template<
typename Fn,
typename Tuple>
332 WrapVoid(Fn && fn, Tuple && args)
333 : value(std::apply(std::forward<Fn>(fn), std::forward<Tuple>(args)))
338 template<
typename T,
typename Placeholder>
347 template<std::
unsigned_
integral Int>
348 bool pack(
Major major, Int value, std::span<uint8_t> & buf);
370 std::optional<Item>
unpack(std::span<uint8_t> & buf);
374 template<std::
unsigned_
integral Int>
403 template<
typename I>
requires std::integral<I> && (!std::same_as<I, bool>)
406 static constexpr size_t bytes =
sizeof(I);
407 static bool encode(I value, std::span<uint8_t> & buf)
411 value = value >= 0 ? value : ~value;
412 using UI = std::make_unsigned_t<I>;
413 return ::Cbor::encode<UI>(major, std::bit_cast<UI>(value), buf);
415 static std::optional<I>
decode(std::span<uint8_t> & buf)
425 value->value = ~value->value;
431 if (value->minor <= minorFromSizeOf(bytes))
433 return {value->value};
437 static size_t maxSize()
443 template<
typename F>
requires std::floating_point<F>
444#if defined(CBOR_HALF_SUPPORT)
445 || std::same_as<F, _Float16>
449 static constexpr size_t bytes =
sizeof(F);
450 using BitT = UintT<bytes * 8>;
451 static bool encode(F value, std::span<uint8_t> & buf)
453#if defined(CBOR_HALF_SUPPORT)
454 if (std::isnan(value))
456 const auto nan = std::bit_cast<uint16_t>(
static_cast<_Float16
>(NAN));
457 return ::Cbor::pack<uint16_t>(Major::Float, nan, buf);
459 const auto v16 =
static_cast<_Float16
>(value);
462 uint16_t b16 = std::bit_cast<uint16_t>(v16);
463 return ::Cbor::pack<uint16_t>(Major::Float, b16, buf);
466 if (std::isnan(value))
468 const auto nan = std::bit_cast<uint32_t>(
static_cast<float>(NAN));
469 return ::Cbor::pack<uint32_t>(Major::Float, nan, buf);
471 const auto v32 =
static_cast<float>(value);
474 const auto b32 = std::bit_cast<uint32_t>(v32);
475 return ::Cbor::pack<uint32_t>(Major::Float, b32, buf);
477 const auto v64 =
static_cast<double>(value);
478 const auto b64 = std::bit_cast<uint64_t>(v64);
479 return ::Cbor::pack<uint64_t>(Major::Float, b64, buf);
481 static std::optional<F> decode(std::span<uint8_t> & buf)
484 if (!value || value->major != Major::Float)
489#if defined(CBOR_HALF_SUPPORT)
490 if (value->minor == Minor::TwoByteFollows && 2 <= bytes)
492 return {
static_cast<F
>(std::bit_cast<_Float16>(
static_cast<uint16_t
>(value->value)))};
495 if (value->minor == Minor::FourByteFollows && 4 <= bytes)
497 return {
static_cast<F
>(std::bit_cast<float>(
static_cast<uint32_t
>(value->value)))};
499 if (value->minor == Minor::EightByteFollows && 8 <= bytes)
501 return {
static_cast<F
>(std::bit_cast<double>(
static_cast<uint64_t
>(value->value)))};
505 static size_t maxSize()
514 static bool encode(
bool value, std::span<uint8_t> & buf)
518 static_cast<uint8_t
>(value ? SimpleValues::True : SimpleValues::False),
521 static std::optional<bool> decode(std::span<uint8_t> & buf)
526 if (value->minor ==
static_cast<Minor>(SimpleValues::True))
530 else if (value->minor ==
static_cast<Minor>(SimpleValues::False))
542 static bool encode(
T * obj, std::span<uint8_t> & buf)
544 return obj !=
nullptr
553 static bool encode(
Undefined, std::span<uint8_t> & buf)
557 static_cast<uint8_t
>(SimpleValues::Undefined), buf);
560 static std::optional<Undefined> decode(std::span<uint8_t> & buf)
563 if (value.has_value() &&
565 value->minor ==
static_cast<Minor>(SimpleValues::Undefined))
576 static bool encode(std::string_view str, std::span<uint8_t> & buf)
589 buf = buf.subspan(1);
598 static bool encode(
const char * str, std::span<uint8_t> & buf)
600 const size_t size = strlen(str);
605 for (
size_t i = 0; i < size; ++i)
612 buf = buf.subspan(1);
618 template<
size_t size>
619 struct Cbor<const char (&)[size]>
621 static bool encode(
const char (&str)[size], std::span<uint8_t> & buf)
627 for (
size_t i = 0; i < size; ++i)
634 buf = buf.subspan(1);
640 template<
typename...
Item>
641 struct Cbor<std::tuple<Item...>>
643 using Tuple = std::tuple<
Item...>;
644 static bool encode(Tuple tup, std::span<uint8_t> & buf)
651 ::Cbor::encode<size_t>(
653 std::tuple_size_v<Tuple>,
655 [&]<
size_t... Index>(std::index_sequence<Index...>)
658 Cbor<std::tuple_element_t<Index, Tuple>>::encode(std::get<Index>(tup), buf) &&
661 }(std::index_sequence_for<
Item...>{});
663 template<
typename...
T>
664 static std::optional<std::tuple<
T...>> transpose(std::tuple<std::optional<T>...> ts)
666 return [&]<
size_t... Index>(std::index_sequence<Index...>)
668 if ((std::get<Index>(ts) && ...))
670 return std::optional<std::tuple<
T...>>{std::in_place, *std::get<Index>(ts)...};
672 return std::optional<std::tuple<
T...>>{};
673 }(std::index_sequence_for<
T...>{});
675 static std::optional<Tuple> decode(std::span<uint8_t> & buf)
683 return transpose(ts);
687 auto sentinel =
unpack(buf);
688 if (sentinel.has_value() &&
692 return transpose(ts);
700 template<
size_t Size>
701 struct Cbor<std::span<uint8_t, Size>>
703 static bool encode(std::span<uint8_t, Size> span, std::span<uint8_t> & buf)
713 if (buf.size() < span.size())
717 std::copy(span.cbegin(), span.cend(), buf.begin());
718 buf = buf.subspan(span.size());
721 static std::optional<std::span<uint8_t, Size>> decode(std::span<uint8_t> & buf)
739 template<
typename T,
size_t Size>
740 struct Cbor<std::array<T, Size>>
742 static bool encode(std::array<T, Size> array, std::span<uint8_t> & buf)
752 for (
const auto & item : array)
761 static std::optional<std::array<T, Size>> decode(std::span<uint8_t> & buf)
766 std::array<T, Size> array =
767 [&]<
size_t... Index>(std::index_sequence<Index...>)
769 return std::array<T, Size>{
772 }(std::make_index_sequence<Size>{});
779 auto sentinel =
unpack(buf);
780 if (sentinel.has_value() &&
792 template<Major major>
796 Sequence(std::span<uint8_t> & buf_,
size_t extent_ = std::dynamic_extent)
797 : buf(buf_), extent(extent_)
799 if (extent == std::dynamic_extent)
808 template<Major parentMajor>
809 Sequence(Sequence<parentMajor> & parentSeq,
size_t extent_ = std::dynamic_extent)
810 : buf(parentSeq.buf), extent(extent_)
813 if (extent == std::dynamic_extent)
824 return extent == std::dynamic_extent || extent == packed;
828 if (extent == std::dynamic_extent)
841 std::span<uint8_t> & buf;
bool packEmbedded(Major major, uint8_t value, std::span< uint8_t > &buf)
Pack a value [0, 23] embedded into the first header byte.
Definition cbor.cpp:16
Minor
Definition cbor.hpp:257
@ EmbeddedFirst
Embedded means no next byte, value is contained within.
Definition cbor.hpp:259
@ OneByteFollows
These contain the next value in the following byte(s).
Definition cbor.hpp:262
@ Indefinite
Definition cbor.hpp:269
std::optional< Item > unpack(std::span< uint8_t > &buf)
Unpack one item.
Definition cbor.cpp:121
SimpleValues
Possible values for Minor when Major is Simple/Float.
Definition cbor.hpp:295
bool pack(Major major, Int value, std::span< uint8_t > &buf)
bool encode(Major major, Int value, std::span< uint8_t > &buf)
Major
Upper three bits of the initial/header byte.
Definition cbor.hpp:222
@ Simple
Definition cbor.hpp:245
@ U64
Value is N the positive integer.
Definition cbor.hpp:224
@ Tagged
Value is the tag, followed by a single item.
Definition cbor.hpp:242
@ Array
Definition cbor.hpp:237
@ Map
Definition cbor.hpp:240
@ Bytes
Definition cbor.hpp:230
@ Utf8
Definition cbor.hpp:234
@ Neg64
Value is -N-1 (note this is ~N in 2s complement)
Definition cbor.hpp:226
static bool encode(I value, std::span< uint8_t > &buf)
Definition cbor.hpp:407
static std::optional< I > decode(std::span< uint8_t > &buf)
Definition cbor.hpp:415
Parametrized CBOR interface.
Definition cbor.hpp:400
Allows materialising void values using a placeholder.
Definition cbor.hpp:312
Simple type utilities e.g. smallest type for given value.