xref: /aosp_15_r20/system/libcppbor/include/cppbor/cppbor.h (revision 0963554132e37a14524024fa04dc9e883c7a8221)
1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <algorithm>
20 #include <cassert>
21 #include <cstddef>
22 #include <cstdint>
23 #include <cstring>
24 #include <functional>
25 #include <iterator>
26 #include <memory>
27 #include <numeric>
28 #include <string>
29 #include <string_view>
30 #include <vector>
31 
32 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || __cplusplus >= 202002L
33 #include <span>
34 #else  // not ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || __cplusplus >= 202002L
35 #include "span.h"
36 #endif  // not ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || __cplusplus >= 202002L
37 
38 #ifdef OS_WINDOWS
39 #include <basetsd.h>
40 
41 #define ssize_t SSIZE_T
42 #endif  // OS_WINDOWS
43 
44 #ifdef TRUE
45 #undef TRUE
46 #endif  // TRUE
47 #ifdef FALSE
48 #undef FALSE
49 #endif  // FALSE
50 
51 namespace cppbor {
52 
53 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || __cplusplus >= 202002L
54 using std::span;
55 #endif  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || __cplusplus >= 202002L
56 
57 enum MajorType : uint8_t {
58     UINT = 0 << 5,
59     NINT = 1 << 5,
60     BSTR = 2 << 5,
61     TSTR = 3 << 5,
62     ARRAY = 4 << 5,
63     MAP = 5 << 5,
64     SEMANTIC = 6 << 5,
65     SIMPLE = 7 << 5,
66 };
67 
68 enum SimpleType {
69     BOOLEAN,
70     NULL_T,
71     FLOAT,
72     DOUBLE,  // Only four supported, as yet.
73 };
74 
75 enum SpecialAddlInfoValues : uint8_t {
76     FALSE = 20,
77     TRUE = 21,
78     NULL_V = 22,
79     ONE_BYTE_LENGTH = 24,
80     TWO_BYTE_LENGTH = 25,
81     FOUR_BYTE_LENGTH = 26,
82     FLOAT_V = 26,
83     EIGHT_BYTE_LENGTH = 27,
84     DOUBLE_V = 27,
85     INDEFINITE_LENGTH = 31,
86 };
87 
88 class Item;
89 class Uint;
90 class Nint;
91 class Int;
92 class Tstr;
93 class Bstr;
94 class Simple;
95 class Bool;
96 class Array;
97 class Map;
98 class Null;
99 class SemanticTag;
100 class EncodedItem;
101 class ViewTstr;
102 class ViewBstr;
103 class Float;
104 class Double;
105 
106 /**
107  * Returns the size of a CBOR header that contains the additional info value addlInfo.
108  */
109 size_t headerSize(uint64_t addlInfo);
110 
111 /**
112  * Encodes a CBOR header with the specified type and additional info into the range [pos, end).
113  * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space
114  * to write the header.
115  */
116 uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end);
117 
118 using EncodeCallback = std::function<void(uint8_t)>;
119 
120 /**
121  * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to
122  * encodeCallback.
123  */
124 void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback);
125 
126 /**
127  * Encodes a CBOR header witht he specified type and additional info, writing each byte to the
128  * provided OutputIterator.
129  */
130 template <typename OutputIterator,
131           typename = std::enable_if_t<std::is_base_of_v<
132                   std::output_iterator_tag,
133                   typename std::iterator_traits<OutputIterator>::iterator_category>>>
encodeHeader(MajorType type,uint64_t addlInfo,OutputIterator iter)134 void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) {
135     return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; });
136 }
137 
138 /**
139  * Item represents a CBOR-encodeable data item.  Item is an abstract interface with a set of virtual
140  * methods that allow encoding of the item or conversion to the appropriate derived type.
141  */
142 class Item {
143   public:
~Item()144     virtual ~Item() {}
145 
146     /**
147      * Returns the CBOR type of the item.
148      */
149     virtual MajorType type() const = 0;
150 
151     // These methods safely downcast an Item to the appropriate subclass.
asInt()152     virtual Int* asInt() { return nullptr; }
asInt()153     const Int* asInt() const { return const_cast<Item*>(this)->asInt(); }
asUint()154     virtual Uint* asUint() { return nullptr; }
asUint()155     const Uint* asUint() const { return const_cast<Item*>(this)->asUint(); }
asNint()156     virtual Nint* asNint() { return nullptr; }
asNint()157     const Nint* asNint() const { return const_cast<Item*>(this)->asNint(); }
asTstr()158     virtual Tstr* asTstr() { return nullptr; }
asTstr()159     const Tstr* asTstr() const { return const_cast<Item*>(this)->asTstr(); }
asBstr()160     virtual Bstr* asBstr() { return nullptr; }
asBstr()161     const Bstr* asBstr() const { return const_cast<Item*>(this)->asBstr(); }
asSimple()162     virtual Simple* asSimple() { return nullptr; }
asSimple()163     const Simple* asSimple() const { return const_cast<Item*>(this)->asSimple(); }
asBool()164     virtual Bool* asBool() { return nullptr; }
asBool()165     const Bool* asBool() const { return const_cast<Item*>(this)->asBool(); }
asNull()166     virtual Null* asNull() { return nullptr; }
asNull()167     const Null* asNull() const { return const_cast<Item*>(this)->asNull(); }
asFloat()168     virtual Float* asFloat() { return nullptr; }
asFloat()169     const Float* asFloat() const { return const_cast<Item*>(this)->asFloat(); }
asDouble()170     virtual Double* asDouble() { return nullptr; }
asDouble()171     const Double* asDouble() const { return const_cast<Item*>(this)->asDouble(); }
172 
asMap()173     virtual Map* asMap() { return nullptr; }
asMap()174     const Map* asMap() const { return const_cast<Item*>(this)->asMap(); }
asArray()175     virtual Array* asArray() { return nullptr; }
asArray()176     const Array* asArray() const { return const_cast<Item*>(this)->asArray(); }
177 
asViewTstr()178     virtual ViewTstr* asViewTstr() { return nullptr; }
asViewTstr()179     const ViewTstr* asViewTstr() const { return const_cast<Item*>(this)->asViewTstr(); }
asViewBstr()180     virtual ViewBstr* asViewBstr() { return nullptr; }
asViewBstr()181     const ViewBstr* asViewBstr() const { return const_cast<Item*>(this)->asViewBstr(); }
182 
183     // Like those above, these methods safely downcast an Item when it's actually a SemanticTag.
184     // However, if you think you want to use these methods, you probably don't.  Typically, the way
185     // you should handle tagged Items is by calling the appropriate method above (e.g. asInt())
186     // which will return a pointer to the tagged Item, rather than the tag itself.  If you want to
187     // find out if the Item* you're holding is to something with one or more tags applied, see
188     // semanticTagCount() and semanticTag() below.
asSemanticTag()189     virtual SemanticTag* asSemanticTag() { return nullptr; }
asSemanticTag()190     const SemanticTag* asSemanticTag() const { return const_cast<Item*>(this)->asSemanticTag(); }
191 
192     /**
193      * Returns the number of semantic tags prefixed to this Item.
194      */
semanticTagCount()195     virtual size_t semanticTagCount() const { return 0; }
196 
197     /**
198      * Returns the semantic tag at the specified nesting level `nesting`, iff `nesting` is less than
199      * the value returned by semanticTagCount().
200      *
201      * CBOR tags are "nested" by applying them in sequence.  The "rightmost" tag is the "inner" tag.
202      * That is, given:
203      *
204      *     4(5(6("AES"))) which encodes as C1 C2 C3 63 414553
205      *
206      * The tstr "AES" is tagged with 6.  The combined entity ("AES" tagged with 6) is tagged with 5,
207      * etc.  So in this example, semanticTagCount() would return 3, and semanticTag(0) would return
208      * 6, semanticTag(1) would return 5, and semanticTag(2) would return 4.  For values of n > 2,
209      * semanticTag(n) would return 0, but this is a meaningless value.
210      *
211      * If this layering is confusing, you probably don't have to worry about it. Nested tagging does
212      * not appear to be common, so semanticTag(0) is the only one you'll use.
213      */
214     virtual uint64_t semanticTag(size_t /* nesting */ = 0) const { return 0; }
215 
216     /**
217      * Returns true if this is a "compound" item, i.e. one that contains one or more other items.
218      */
isCompound()219     virtual bool isCompound() const { return false; }
220 
221     bool operator==(const Item& other) const&;
222     bool operator!=(const Item& other) const& { return !(*this == other); }
223 
224     /**
225      * Returns the number of bytes required to encode this Item into CBOR.  Note that if this is a
226      * complex Item, calling this method will require walking the whole tree.
227      */
228     virtual size_t encodedSize() const = 0;
229 
230     /**
231      * Encodes the Item into buffer referenced by range [*pos, end).  Returns a pointer to one past
232      * the last position written.  Returns nullptr if there isn't enough space to encode.
233      */
234     virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0;
235 
236     /**
237      * Encodes the Item by passing each encoded byte to encodeCallback.
238      */
239     virtual void encode(EncodeCallback encodeCallback) const = 0;
240 
241     /**
242      * Clones the Item
243      */
244     virtual std::unique_ptr<Item> clone() const = 0;
245 
246     /**
247      * Encodes the Item into the provided OutputIterator.
248      */
249     template <typename OutputIterator,
250               typename = typename std::iterator_traits<OutputIterator>::iterator_category>
encode(OutputIterator i)251     void encode(OutputIterator i) const {
252         return encode([&](uint8_t v) { *i++ = v; });
253     }
254 
255     /**
256      * Encodes the Item into a new std::vector<uint8_t>.
257      */
encode()258     std::vector<uint8_t> encode() const {
259         std::vector<uint8_t> retval;
260         retval.reserve(encodedSize());
261         encode(std::back_inserter(retval));
262         return retval;
263     }
264 
265     /**
266      * Encodes the Item into a new std::string.
267      */
toString()268     std::string toString() const {
269         std::string retval;
270         retval.reserve(encodedSize());
271         encode([&](uint8_t v) { retval.push_back(v); });
272         return retval;
273     }
274 
275     /**
276      * Encodes only the header of the Item.
277      */
encodeHeader(uint64_t addlInfo,uint8_t * pos,const uint8_t * end)278     inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const {
279         return ::cppbor::encodeHeader(type(), addlInfo, pos, end);
280     }
281 
282     /**
283      * Encodes only the header of the Item.
284      */
encodeHeader(uint64_t addlInfo,EncodeCallback encodeCallback)285     inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const {
286         ::cppbor::encodeHeader(type(), addlInfo, encodeCallback);
287     }
288 };
289 
290 /**
291  * EncodedItem represents a bit of already-encoded CBOR. Caveat emptor: It does no checking to
292  * ensure that the provided data is a valid encoding, cannot be meaninfully-compared with other
293  * kinds of items and you cannot use the as*() methods to find out what's inside it.
294  */
295 class EncodedItem : public Item {
296   public:
EncodedItem(std::vector<uint8_t> value)297     explicit EncodedItem(std::vector<uint8_t> value) : mValue(std::move(value)) {}
298 
299     bool operator==(const EncodedItem& other) const& { return mValue == other.mValue; }
300 
301     // Type can't be meaningfully-obtained. We could extract the type from the first byte and return
302     // it, but you can't do any of the normal things with an EncodedItem so there's no point.
type()303     MajorType type() const override {
304         assert(false);
305         return static_cast<MajorType>(-1);
306     }
encodedSize()307     size_t encodedSize() const override { return mValue.size(); }
encode(uint8_t * pos,const uint8_t * end)308     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
309         if (end - pos < static_cast<ssize_t>(mValue.size())) return nullptr;
310         return std::copy(mValue.begin(), mValue.end(), pos);
311     }
encode(EncodeCallback encodeCallback)312     void encode(EncodeCallback encodeCallback) const override {
313         std::for_each(mValue.begin(), mValue.end(), encodeCallback);
314     }
clone()315     std::unique_ptr<Item> clone() const override { return std::make_unique<EncodedItem>(mValue); }
316 
317   private:
318     std::vector<uint8_t> mValue;
319 };
320 
321 /**
322  * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about
323  * the sign.
324  */
325 class Int : public Item {
326   public:
327     bool operator==(const Int& other) const& { return value() == other.value(); }
328 
329     virtual int64_t value() const = 0;
330     using Item::asInt;
asInt()331     Int* asInt() override { return this; }
332 };
333 
334 /**
335  * Uint is a concrete Item that implements CBOR major type 0.
336  */
337 class Uint : public Int {
338   public:
339     static constexpr MajorType kMajorType = UINT;
340 
Uint(uint64_t v)341     explicit Uint(uint64_t v) : mValue(v) {}
342 
343     bool operator==(const Uint& other) const& { return mValue == other.mValue; }
344 
type()345     MajorType type() const override { return kMajorType; }
346     using Item::asUint;
asUint()347     Uint* asUint() override { return this; }
348 
encodedSize()349     size_t encodedSize() const override { return headerSize(mValue); }
350 
value()351     int64_t value() const override { return mValue; }
unsignedValue()352     uint64_t unsignedValue() const { return mValue; }
353 
354     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)355     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
356         return encodeHeader(mValue, pos, end);
357     }
encode(EncodeCallback encodeCallback)358     void encode(EncodeCallback encodeCallback) const override {
359         encodeHeader(mValue, encodeCallback);
360     }
361 
clone()362     std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); }
363 
364   private:
365     uint64_t mValue;
366 };
367 
368 /**
369  * Nint is a concrete Item that implements CBOR major type 1.
370 
371  * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only
372  * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1].  It cannot
373  * express values in the range [std::numeric_limits<int64_t>::min() - 1,
374  * -std::numeric_limits<uint64_t>::max()].
375  */
376 class Nint : public Int {
377   public:
378     static constexpr MajorType kMajorType = NINT;
379 
380     explicit Nint(int64_t v);
381 
382     bool operator==(const Nint& other) const& { return mValue == other.mValue; }
383 
type()384     MajorType type() const override { return kMajorType; }
385     using Item::asNint;
asNint()386     Nint* asNint() override { return this; }
encodedSize()387     size_t encodedSize() const override { return headerSize(addlInfo()); }
388 
value()389     int64_t value() const override { return mValue; }
390 
391     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)392     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
393         return encodeHeader(addlInfo(), pos, end);
394     }
encode(EncodeCallback encodeCallback)395     void encode(EncodeCallback encodeCallback) const override {
396         encodeHeader(addlInfo(), encodeCallback);
397     }
398 
clone()399     std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
400 
401   private:
addlInfo()402     uint64_t addlInfo() const { return -1ll - mValue; }
403 
404     int64_t mValue;
405 };
406 
407 /**
408  * Bstr is a concrete Item that implements major type 2.
409  */
410 class Bstr : public Item {
411   public:
412     static constexpr MajorType kMajorType = BSTR;
413 
414     // Construct an empty Bstr
Bstr()415     explicit Bstr() {}
416 
417     // Construct from a vector
Bstr(std::vector<uint8_t> v)418     explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {}
419 
420     // Construct from a string
Bstr(const std::string & v)421     explicit Bstr(const std::string& v)
422         : mValue(reinterpret_cast<const uint8_t*>(v.data()),
423                  reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {}
424 
425     // Construct from a pointer/size pair
Bstr(const std::pair<const uint8_t *,size_t> & buf)426     explicit Bstr(const std::pair<const uint8_t*, size_t>& buf)
427         : mValue(buf.first, buf.first + buf.second) {}
428 
429     // Construct from a pair of iterators
430     template <typename I1, typename I2,
431               typename = typename std::iterator_traits<I1>::iterator_category,
432               typename = typename std::iterator_traits<I2>::iterator_category>
Bstr(const std::pair<I1,I2> & pair)433     explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
434 
435     // Construct from an iterator range.
436     template <typename I1, typename I2,
437               typename = typename std::iterator_traits<I1>::iterator_category,
438               typename = typename std::iterator_traits<I2>::iterator_category>
Bstr(I1 begin,I2 end)439     Bstr(I1 begin, I2 end) : mValue(begin, end) {}
440 
441     bool operator==(const Bstr& other) const& { return mValue == other.mValue; }
442 
type()443     MajorType type() const override { return kMajorType; }
444     using Item::asBstr;
asBstr()445     Bstr* asBstr() override { return this; }
encodedSize()446     size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
447     using Item::encode;
448     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
encode(EncodeCallback encodeCallback)449     void encode(EncodeCallback encodeCallback) const override {
450         encodeHeader(mValue.size(), encodeCallback);
451         encodeValue(encodeCallback);
452     }
453 
value()454     const std::vector<uint8_t>& value() const { return mValue; }
moveValue()455     std::vector<uint8_t>&& moveValue() { return std::move(mValue); }
456 
clone()457     std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); }
458 
459   protected:
460     std::vector<uint8_t> mValue;
461 
462   private:
463     void encodeValue(EncodeCallback encodeCallback) const;
464 };
465 
466 /**
467  * ViewBstr is a read-only version of Bstr backed by span
468  */
469 class ViewBstr : public Item {
470   public:
471     static constexpr MajorType kMajorType = BSTR;
472 
473     // Construct an empty ViewBstr
ViewBstr()474     explicit ViewBstr() {}
475 
476     // Construct from a span of uint8_t values
ViewBstr(span<const uint8_t> v)477     explicit ViewBstr(span<const uint8_t> v) : mView(std::move(v)) {}
478 
479     // Construct from a string_view
ViewBstr(std::string_view v)480     explicit ViewBstr(std::string_view v)
481         : mView(reinterpret_cast<const uint8_t*>(v.data()), v.size()) {}
482 
483     // Construct from an iterator range
484     template <typename I1, typename I2,
485               typename = typename std::iterator_traits<I1>::iterator_category,
486               typename = typename std::iterator_traits<I2>::iterator_category>
ViewBstr(I1 begin,I2 end)487     ViewBstr(I1 begin, I2 end) : mView(begin, end) {}
488 
489     // Construct from a uint8_t pointer pair
ViewBstr(const uint8_t * begin,const uint8_t * end)490     ViewBstr(const uint8_t* begin, const uint8_t* end) : mView(begin, std::distance(begin, end)) {}
491 
492     bool operator==(const ViewBstr& other) const& {
493         return std::equal(mView.begin(), mView.end(), other.mView.begin(), other.mView.end());
494     }
495 
type()496     MajorType type() const override { return kMajorType; }
497     using Item::asViewBstr;
asViewBstr()498     ViewBstr* asViewBstr() override { return this; }
encodedSize()499     size_t encodedSize() const override { return headerSize(mView.size()) + mView.size(); }
500     using Item::encode;
501     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
encode(EncodeCallback encodeCallback)502     void encode(EncodeCallback encodeCallback) const override {
503         encodeHeader(mView.size(), encodeCallback);
504         encodeValue(encodeCallback);
505     }
506 
view()507     const span<const uint8_t>& view() const { return mView; }
508 
clone()509     std::unique_ptr<Item> clone() const override { return std::make_unique<ViewBstr>(mView); }
510 
511   private:
512     void encodeValue(EncodeCallback encodeCallback) const;
513 
514     span<const uint8_t> mView;
515 };
516 
517 /**
518  * Tstr is a concrete Item that implements major type 3.
519  */
520 class Tstr : public Item {
521   public:
522     static constexpr MajorType kMajorType = TSTR;
523 
524     // Construct an empty Tstr
Tstr()525     explicit Tstr() {}
526 
527     // Construct from a string
Tstr(std::string v)528     explicit Tstr(std::string v) : mValue(std::move(v)) {}
529 
530     // Construct from a string_view
Tstr(const std::string_view & v)531     explicit Tstr(const std::string_view& v) : mValue(v) {}
532 
533     // Construct from a C string
Tstr(const char * v)534     explicit Tstr(const char* v) : mValue(std::string(v)) {}
535 
536     // Construct from a pair of iterators
537     template <typename I1, typename I2,
538               typename = typename std::iterator_traits<I1>::iterator_category,
539               typename = typename std::iterator_traits<I2>::iterator_category>
Tstr(const std::pair<I1,I2> & pair)540     explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {}
541 
542     // Construct from an iterator range
543     template <typename I1, typename I2,
544               typename = typename std::iterator_traits<I1>::iterator_category,
545               typename = typename std::iterator_traits<I2>::iterator_category>
Tstr(I1 begin,I2 end)546     Tstr(I1 begin, I2 end) : mValue(begin, end) {}
547 
548     bool operator==(const Tstr& other) const& { return mValue == other.mValue; }
549 
type()550     MajorType type() const override { return kMajorType; }
551     using Item::asTstr;
asTstr()552     Tstr* asTstr() override { return this; }
encodedSize()553     size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); }
554     using Item::encode;
555     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
encode(EncodeCallback encodeCallback)556     void encode(EncodeCallback encodeCallback) const override {
557         encodeHeader(mValue.size(), encodeCallback);
558         encodeValue(encodeCallback);
559     }
560 
value()561     const std::string& value() const { return mValue; }
moveValue()562     std::string&& moveValue() { return std::move(mValue); }
563 
clone()564     std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); }
565 
566   protected:
567     std::string mValue;
568 
569   private:
570     void encodeValue(EncodeCallback encodeCallback) const;
571 };
572 
573 /**
574  * ViewTstr is a read-only version of Tstr backed by std::string_view
575  */
576 class ViewTstr : public Item {
577   public:
578     static constexpr MajorType kMajorType = TSTR;
579 
580     // Construct an empty ViewTstr
ViewTstr()581     explicit ViewTstr() {}
582 
583     // Construct from a string_view
ViewTstr(std::string_view v)584     explicit ViewTstr(std::string_view v) : mView(std::move(v)) {}
585 
586     // Construct from an iterator range
587     template <typename I1, typename I2,
588               typename = typename std::iterator_traits<I1>::iterator_category,
589               typename = typename std::iterator_traits<I2>::iterator_category>
ViewTstr(I1 begin,I2 end)590     ViewTstr(I1 begin, I2 end) : mView(begin, end) {}
591 
592     // Construct from a uint8_t pointer pair
ViewTstr(const uint8_t * begin,const uint8_t * end)593     ViewTstr(const uint8_t* begin, const uint8_t* end)
594         : mView(reinterpret_cast<const char*>(begin), std::distance(begin, end)) {}
595 
596     bool operator==(const ViewTstr& other) const& { return mView == other.mView; }
597 
type()598     MajorType type() const override { return kMajorType; }
599     using Item::asViewTstr;
asViewTstr()600     ViewTstr* asViewTstr() override { return this; }
encodedSize()601     size_t encodedSize() const override { return headerSize(mView.size()) + mView.size(); }
602     using Item::encode;
603     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
encode(EncodeCallback encodeCallback)604     void encode(EncodeCallback encodeCallback) const override {
605         encodeHeader(mView.size(), encodeCallback);
606         encodeValue(encodeCallback);
607     }
608 
view()609     const std::string_view& view() const { return mView; }
610 
clone()611     std::unique_ptr<Item> clone() const override { return std::make_unique<ViewTstr>(mView); }
612 
613   private:
614     void encodeValue(EncodeCallback encodeCallback) const;
615 
616     std::string_view mView;
617 };
618 
619 /*
620  * Array is a concrete Item that implements CBOR major type 4.
621  *
622  * Note that Arrays are not copyable.  This is because copying them is expensive and making them
623  * move-only ensures that they're never copied accidentally.  If you actually want to copy an Array,
624  * use the clone() method.
625  */
626 class Array : public Item {
627   public:
628     static constexpr MajorType kMajorType = ARRAY;
629 
630     Array() = default;
631     Array(const Array& other) = delete;
632     Array(Array&&) = default;
633     Array& operator=(const Array&) = delete;
634     Array& operator=(Array&&) = default;
635 
636     bool operator==(const Array& other) const&;
637 
638     /**
639      * Construct an Array from a variable number of arguments of different types.  See
640      * details::makeItem below for details on what types may be provided.  In general, this accepts
641      * all of the types you'd expect and doest the things you'd expect (integral values are addes as
642      * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.).
643      */
644     template <typename... Args, typename Enable>
645     Array(Args&&... args);
646 
647     /**
648      * The above variadic constructor is disabled if sizeof(Args) != 1, so special
649      * case an explicit Array constructor for creating an Array with one Item.
650      */
651     template <typename T, typename Enable>
652     explicit Array(T&& v);
653 
654     /**
655      * Append a single element to the Array, of any compatible type.
656      */
657     template <typename T>
658     Array& add(T&& v) &;
659     template <typename T>
660     Array&& add(T&& v) &&;
661 
isCompound()662     bool isCompound() const override { return true; }
663 
size()664     virtual size_t size() const { return mEntries.size(); }
665 
encodedSize()666     size_t encodedSize() const override {
667         return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()),
668                                [](size_t sum, auto& entry) { return sum + entry->encodedSize(); });
669     }
670 
671     using Item::encode;  // Make base versions visible.
672     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
673     void encode(EncodeCallback encodeCallback) const override;
674 
675     const std::unique_ptr<Item>& operator[](size_t index) const { return get(index); }
676     std::unique_ptr<Item>& operator[](size_t index) { return get(index); }
677 
get(size_t index)678     const std::unique_ptr<Item>& get(size_t index) const { return mEntries[index]; }
get(size_t index)679     std::unique_ptr<Item>& get(size_t index) { return mEntries[index]; }
680 
type()681     MajorType type() const override { return kMajorType; }
682     using Item::asArray;
asArray()683     Array* asArray() override { return this; }
684 
685     std::unique_ptr<Item> clone() const override;
686 
begin()687     auto begin() { return mEntries.begin(); }
begin()688     auto begin() const { return mEntries.begin(); }
end()689     auto end() { return mEntries.end(); }
end()690     auto end() const { return mEntries.end(); }
691 
692   protected:
693     std::vector<std::unique_ptr<Item>> mEntries;
694 };
695 
696 /*
697  * Map is a concrete Item that implements CBOR major type 5.
698  *
699  * Note that Maps are not copyable.  This is because copying them is expensive and making them
700  * move-only ensures that they're never copied accidentally.  If you actually want to copy a
701  * Map, use the clone() method.
702  */
703 class Map : public Item {
704   public:
705     static constexpr MajorType kMajorType = MAP;
706 
707     using entry_type = std::pair<std::unique_ptr<Item>, std::unique_ptr<Item>>;
708 
709     Map() = default;
710     Map(const Map& other) = delete;
711     Map(Map&&) = default;
712     Map& operator=(const Map& other) = delete;
713     Map& operator=(Map&&) = default;
714 
715     bool operator==(const Map& other) const&;
716 
717     /**
718      * Construct a Map from a variable number of arguments of different types.  An even number of
719      * arguments must be provided (this is verified statically). See details::makeItem below for
720      * details on what types may be provided.  In general, this accepts all of the types you'd
721      * expect and doest the things you'd expect (integral values are addes as Uint or Nint,
722      * std::string and char* are added as Tstr, bools are added as Bool, etc.).
723      */
724     template <typename... Args, typename Enable>
725     Map(Args&&... args);
726 
727     /**
728      * Append a key/value pair to the Map, of any compatible types.
729      */
730     template <typename Key, typename Value>
731     Map& add(Key&& key, Value&& value) &;
732     template <typename Key, typename Value>
733     Map&& add(Key&& key, Value&& value) &&;
734 
isCompound()735     bool isCompound() const override { return true; }
736 
size()737     virtual size_t size() const { return mEntries.size(); }
738 
encodedSize()739     size_t encodedSize() const override {
740         return std::accumulate(
741                 mEntries.begin(), mEntries.end(), headerSize(size()), [](size_t sum, auto& entry) {
742                     return sum + entry.first->encodedSize() + entry.second->encodedSize();
743                 });
744     }
745 
746     using Item::encode;  // Make base versions visible.
747     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
748     void encode(EncodeCallback encodeCallback) const override;
749 
750     /**
751      * Find and return the value associated with `key`, if any.
752      *
753      * If the searched-for `key` is not present, returns `nullptr`.
754      *
755      * Note that if the map is canonicalized (sorted), Map::get() performs a binary search.  If your
756      * map is large and you're searching in it many times, it may be worthwhile to canonicalize it
757      * to make Map::get() faster.  Any use of a method that might modify the map disables the
758      * speedup.
759      */
760     template <typename Key, typename Enable>
761     const std::unique_ptr<Item>& get(Key key) const;
762 
763     // Note that use of non-const operator[] marks the map as not canonicalized.
764     auto& operator[](size_t index) {
765         mCanonicalized = false;
766         return mEntries[index];
767     }
768     const auto& operator[](size_t index) const { return mEntries[index]; }
769 
type()770     MajorType type() const override { return kMajorType; }
771     using Item::asMap;
asMap()772     Map* asMap() override { return this; }
773 
774     /**
775      * Sorts the map in canonical order, as defined in RFC 7049. Use this before encoding if you
776      * want canonicalization; cppbor does not canonicalize by default, though the integer encodings
777      * are always canonical and cppbor does not support indefinite-length encodings, so map order
778      * canonicalization is the only thing that needs to be done.
779      *
780      * @param recurse If set to true, canonicalize() will also walk the contents of the map and
781      * canonicalize any contained maps as well.
782      */
783     Map& canonicalize(bool recurse = false) &;
784     Map&& canonicalize(bool recurse = false) && {
785         canonicalize(recurse);
786         return std::move(*this);
787     }
788 
isCanonical()789     bool isCanonical() { return mCanonicalized; }
790 
791     std::unique_ptr<Item> clone() const override;
792 
begin()793     auto begin() {
794         mCanonicalized = false;
795         return mEntries.begin();
796     }
begin()797     auto begin() const { return mEntries.begin(); }
end()798     auto end() {
799         mCanonicalized = false;
800         return mEntries.end();
801     }
end()802     auto end() const { return mEntries.end(); }
803 
804     // Returns true if a < b, per CBOR map key canonicalization rules.
805     static bool keyLess(const Item* a, const Item* b);
806 
807   protected:
808     std::vector<entry_type> mEntries;
809 
810   private:
811     bool mCanonicalized = false;
812 };
813 
814 class SemanticTag : public Item {
815   public:
816     static constexpr MajorType kMajorType = SEMANTIC;
817 
818     template <typename T>
819     SemanticTag(uint64_t tagValue, T&& taggedItem);
820     SemanticTag(const SemanticTag& other) = delete;
821     SemanticTag(SemanticTag&&) = default;
822     SemanticTag& operator=(const SemanticTag& other) = delete;
823     SemanticTag& operator=(SemanticTag&&) = default;
824 
825     bool operator==(const SemanticTag& other) const& {
826         return mValue == other.mValue && *mTaggedItem == *other.mTaggedItem;
827     }
828 
isCompound()829     bool isCompound() const override { return true; }
830 
size()831     virtual size_t size() const { return 1; }
832 
833     // Encoding returns the tag + enclosed Item.
encodedSize()834     size_t encodedSize() const override { return headerSize(mValue) + mTaggedItem->encodedSize(); }
835 
836     using Item::encode;  // Make base versions visible.
837     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override;
838     void encode(EncodeCallback encodeCallback) const override;
839 
840     // type() is a bit special.  In normal usage it should return the wrapped type, but during
841     // parsing when we haven't yet parsed the tagged item, it needs to return SEMANTIC.
type()842     MajorType type() const override { return mTaggedItem ? mTaggedItem->type() : SEMANTIC; }
843     using Item::asSemanticTag;
asSemanticTag()844     SemanticTag* asSemanticTag() override { return this; }
845 
846     // Type information reflects the enclosed Item.  Note that if the immediately-enclosed Item is
847     // another tag, these methods will recurse down to the non-tag Item.
848     using Item::asInt;
asInt()849     Int* asInt() override { return mTaggedItem->asInt(); }
850     using Item::asUint;
asUint()851     Uint* asUint() override { return mTaggedItem->asUint(); }
852     using Item::asNint;
asNint()853     Nint* asNint() override { return mTaggedItem->asNint(); }
854     using Item::asTstr;
asTstr()855     Tstr* asTstr() override { return mTaggedItem->asTstr(); }
856     using Item::asBstr;
asBstr()857     Bstr* asBstr() override { return mTaggedItem->asBstr(); }
858     using Item::asSimple;
asSimple()859     Simple* asSimple() override { return mTaggedItem->asSimple(); }
860     using Item::asMap;
asMap()861     Map* asMap() override { return mTaggedItem->asMap(); }
862     using Item::asArray;
asArray()863     Array* asArray() override { return mTaggedItem->asArray(); }
864     using Item::asViewTstr;
asViewTstr()865     ViewTstr* asViewTstr() override { return mTaggedItem->asViewTstr(); }
866     using Item::asViewBstr;
asViewBstr()867     ViewBstr* asViewBstr() override { return mTaggedItem->asViewBstr(); }
868 
869     std::unique_ptr<Item> clone() const override;
870 
871     size_t semanticTagCount() const override;
872     uint64_t semanticTag(size_t nesting = 0) const override;
873 
874   protected:
875     SemanticTag() = default;
SemanticTag(uint64_t value)876     SemanticTag(uint64_t value) : mValue(value) {}
877     uint64_t mValue;
878     std::unique_ptr<Item> mTaggedItem;
879 };
880 
881 /**
882  * Simple is abstract Item that implements CBOR major type 7.  It is intended to be subclassed to
883  * create concrete Simple types.  At present only Bool is provided.
884  */
885 class Simple : public Item {
886   public:
887     static constexpr MajorType kMajorType = SIMPLE;
888 
889     bool operator==(const Simple& other) const&;
890 
891     virtual SimpleType simpleType() const = 0;
type()892     MajorType type() const override { return kMajorType; }
893 
asSimple()894     Simple* asSimple() override { return this; }
895 };
896 
897 /**
898  * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE
899  * and FALSE.
900  */
901 class Bool : public Simple {
902   public:
903     static constexpr SimpleType kSimpleType = BOOLEAN;
904 
Bool(bool v)905     explicit Bool(bool v) : mValue(v) {}
906 
907     bool operator==(const Bool& other) const& { return mValue == other.mValue; }
908 
simpleType()909     SimpleType simpleType() const override { return kSimpleType; }
asBool()910     Bool* asBool() override { return this; }
911 
encodedSize()912     size_t encodedSize() const override { return 1; }
913 
914     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)915     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
916         return encodeHeader(mValue ? TRUE : FALSE, pos, end);
917     }
encode(EncodeCallback encodeCallback)918     void encode(EncodeCallback encodeCallback) const override {
919         encodeHeader(mValue ? TRUE : FALSE, encodeCallback);
920     }
921 
value()922     bool value() const { return mValue; }
923 
clone()924     std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); }
925 
926   private:
927     bool mValue;
928 };
929 
930 /**
931  * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL
932  */
933 class Null : public Simple {
934   public:
935     static constexpr SimpleType kSimpleType = NULL_T;
936 
Null()937     explicit Null() {}
938 
simpleType()939     SimpleType simpleType() const override { return kSimpleType; }
asNull()940     Null* asNull() override { return this; }
941 
encodedSize()942     size_t encodedSize() const override { return 1; }
943 
944     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)945     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
946         return encodeHeader(NULL_V, pos, end);
947     }
encode(EncodeCallback encodeCallback)948     void encode(EncodeCallback encodeCallback) const override {
949         encodeHeader(NULL_V, encodeCallback);
950     }
951 
clone()952     std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); }
953 };
954 
955 #if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
956 /**
957  * Float is a concrete type that implements CBOR major type 7, with additional item value for
958  * FLOAT.
959  */
960 class Float : public Simple {
961   public:
962     static constexpr SimpleType kSimpleType = FLOAT;
963 
Float(float v)964     explicit Float(float v) : mValue(v) {}
965 
simpleType()966     SimpleType simpleType() const override { return kSimpleType; }
asFloat()967     Float* asFloat() override { return this; }
968 
value()969     float value() const { return mValue; }
encodedSize()970     size_t encodedSize() const override { return 5; }
971 
972     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)973     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
974         uint32_t bits;
975         std::memcpy(&bits, &mValue, sizeof(float));
976         return encodeHeader(bits, pos, end);
977     }
encode(EncodeCallback encodeCallback)978     void encode(EncodeCallback encodeCallback) const override {
979         uint32_t bits;
980         std::memcpy(&bits, &mValue, sizeof(float));
981         encodeHeader(bits, encodeCallback);
982     }
983 
clone()984     std::unique_ptr<Item> clone() const override { return std::make_unique<Float>(mValue); }
985 
986   private:
987     float mValue;
988 };
989 #endif  // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
990 
991 #if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
992 /**
993  * Double is a concrete type that implements CBOR major type 7, with additional item value for
994  * DOUBLE.
995  */
996 class Double : public Simple {
997   public:
998     static constexpr SimpleType kSimpleType = DOUBLE;
999 
Double(double v)1000     explicit Double(double v) : mValue(v) {}
1001 
simpleType()1002     SimpleType simpleType() const override { return kSimpleType; }
asDouble()1003     Double* asDouble() override { return this; }
1004 
value()1005     double value() const { return mValue; }
encodedSize()1006     size_t encodedSize() const override { return 9; }
1007 
1008     using Item::encode;
encode(uint8_t * pos,const uint8_t * end)1009     uint8_t* encode(uint8_t* pos, const uint8_t* end) const override {
1010         uint64_t bits;
1011         std::memcpy(&bits, &mValue, sizeof(double));
1012         return encodeHeader(bits, pos, end);
1013     }
encode(EncodeCallback encodeCallback)1014     void encode(EncodeCallback encodeCallback) const override {
1015         uint64_t bits;
1016         std::memcpy(&bits, &mValue, sizeof(double));
1017         encodeHeader(bits, encodeCallback);
1018     }
1019 
clone()1020     std::unique_ptr<Item> clone() const override { return std::make_unique<Double>(mValue); }
1021 
1022   private:
1023     double mValue;
1024 };
1025 #endif  // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
1026 
1027 /**
1028  * Returns pretty-printed CBOR for |item|
1029  *
1030  * If a byte-string is larger than |maxBStrSize| its contents will not be printed, instead the value
1031  * of the form "<bstr size=1099016 sha1=ef549cca331f73dfae2090e6a37c04c23f84b07b>" will be
1032  * printed. Pass zero for |maxBStrSize| to disable this.
1033  *
1034  * The |mapKeysToNotPrint| parameter specifies the name of map values to not print. This is useful
1035  * for unit tests.
1036  */
1037 std::string prettyPrint(const Item* item, size_t maxBStrSize = 32,
1038                         const std::vector<std::string>& mapKeysToNotPrint = {});
1039 
1040 /**
1041  * Returns pretty-printed CBOR for |value|.
1042  *
1043  * Only valid CBOR should be passed to this function.
1044  *
1045  * If a byte-string is larger than |maxBStrSize| its contents will not be printed, instead the value
1046  * of the form "<bstr size=1099016 sha1=ef549cca331f73dfae2090e6a37c04c23f84b07b>" will be
1047  * printed. Pass zero for |maxBStrSize| to disable this.
1048  *
1049  * The |mapKeysToNotPrint| parameter specifies the name of map values to not print. This is useful
1050  * for unit tests.
1051  */
1052 std::string prettyPrint(const std::vector<uint8_t>& encodedCbor, size_t maxBStrSize = 32,
1053                         const std::vector<std::string>& mapKeysToNotPrint = {});
1054 
1055 /**
1056  * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem.
1057  */
1058 namespace details {
1059 
1060 template <typename T, typename V, typename Enable = void>
1061 struct is_iterator_pair_over : public std::false_type {};
1062 
1063 template <typename I1, typename I2, typename V>
1064 struct is_iterator_pair_over<
1065         std::pair<I1, I2>, V,
1066         typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>>
1067     : public std::true_type {};
1068 
1069 template <typename T, typename V, typename Enable = void>
1070 struct is_unique_ptr_of_subclass_of_v : public std::false_type {};
1071 
1072 template <typename T, typename P>
1073 struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>,
1074                                       typename std::enable_if_t<std::is_base_of_v<T, P>>>
1075     : public std::true_type {};
1076 
1077 /* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair
1078  *     of iterators (4)*/
1079 template <typename T, typename Enable = void>
1080 struct is_text_type_v : public std::false_type {};
1081 
1082 template <typename T>
1083 struct is_text_type_v<
1084         T, typename std::enable_if_t<
1085                    /* case 1 */  //
1086                    std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string>
1087                    /* case 2 */  //
1088                    || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view>
1089                    /* case 3 */                                                 //
1090                    || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*>  //
1091                    || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*>
1092                    /* case 4 */
1093                    || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {};
1094 
1095 /**
1096  * Construct a unique_ptr<Item> from many argument types. Accepts:
1097  *
1098  * (a) booleans;
1099  * (b) integers, all sizes and signs;
1100  * (c) text strings, as defined by is_text_type_v above;
1101  * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T>
1102  *     (d3); and
1103  * (e) Item subclass instances, including Array and Map.  Items may be provided by naked pointer
1104  *     (e1), unique_ptr (e2), reference (e3) or value (e3).  If provided by reference or value, will
1105  *     be moved if possible.  If provided by pointer, ownership is taken.
1106  * (f) null pointer;
1107  * (g) enums, using the underlying integer value.
1108  */
1109 template <typename T>
1110 std::unique_ptr<Item> makeItem(T v) {
1111     Item* p = nullptr;
1112     if constexpr (/* case a */ std::is_same_v<T, bool>) {
1113         p = new Bool(v);
1114     } else if constexpr (/* case b */ std::is_integral_v<T>) {  // b
1115         if (v < 0) {
1116             p = new Nint(v);
1117         } else {
1118             p = new Uint(static_cast<uint64_t>(v));
1119         }
1120     } else if constexpr (/* case c */  //
1121                          details::is_text_type_v<T>::value) {
1122         p = new Tstr(v);
1123     } else if constexpr (/* case d1 */  //
1124                          std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
1125                                         std::vector<uint8_t>>
1126                          /* case d2 */  //
1127                          || details::is_iterator_pair_over<T, uint8_t>::value
1128                          /* case d3 */  //
1129                          || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
1130                                            std::pair<uint8_t*, size_t>>) {
1131         p = new Bstr(v);
1132     } else if constexpr (/* case e1 */  //
1133                          std::is_pointer_v<T> &&
1134                          std::is_base_of_v<Item, std::remove_pointer_t<T>>) {
1135         p = v;
1136     } else if constexpr (/* case e2 */  //
1137                          details::is_unique_ptr_of_subclass_of_v<Item, T>::value) {
1138         p = v.release();
1139     } else if constexpr (/* case e3 */  //
1140                          std::is_base_of_v<Item, T>) {
1141         p = new T(std::move(v));
1142     } else if constexpr (/* case f */ std::is_null_pointer_v<T>) {
1143         p = new Null();
1144     } else if constexpr (/* case g */ std::is_enum_v<T>) {
1145         return makeItem(static_cast<std::underlying_type_t<T>>(v));
1146     } else {
1147         // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one
1148         // of the above ifs matches.  But static_assert(false) always triggers.
1149         static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type");
1150     }
1151     return std::unique_ptr<Item>(p);
1152 }
1153 
1154 inline void map_helper(Map& /* map */) {}
1155 
1156 template <typename Key, typename Value, typename... Rest>
1157 inline void map_helper(Map& map, Key&& key, Value&& value, Rest&&... rest) {
1158     map.add(std::forward<Key>(key), std::forward<Value>(value));
1159     map_helper(map, std::forward<Rest>(rest)...);
1160 }
1161 
1162 }  // namespace details
1163 
1164 template <typename... Args,
1165           /* Prevent implicit construction with a single argument. */
1166           typename = std::enable_if_t<(sizeof...(Args)) != 1>>
1167 Array::Array(Args&&... args) {
1168     mEntries.reserve(sizeof...(args));
1169     (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...);
1170 }
1171 
1172 template <typename T,
1173           /* Prevent use as copy constructor. */
1174           typename = std::enable_if_t<
1175                   !std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<T>>>>>
1176 Array::Array(T&& v) {
1177     mEntries.push_back(details::makeItem(std::forward<T>(v)));
1178 }
1179 
1180 template <typename T>
1181 Array& Array::add(T&& v) & {
1182     mEntries.push_back(details::makeItem(std::forward<T>(v)));
1183     return *this;
1184 }
1185 
1186 template <typename T>
1187 Array&& Array::add(T&& v) && {
1188     mEntries.push_back(details::makeItem(std::forward<T>(v)));
1189     return std::move(*this);
1190 }
1191 
1192 template <typename... Args,
1193           /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>>
1194 Map::Map(Args&&... args) {
1195     static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries");
1196     mEntries.reserve(sizeof...(args) / 2);
1197     details::map_helper(*this, std::forward<Args>(args)...);
1198 }
1199 
1200 template <typename Key, typename Value>
1201 Map& Map::add(Key&& key, Value&& value) & {
1202     mEntries.push_back({details::makeItem(std::forward<Key>(key)),
1203                         details::makeItem(std::forward<Value>(value))});
1204     mCanonicalized = false;
1205     return *this;
1206 }
1207 
1208 template <typename Key, typename Value>
1209 Map&& Map::add(Key&& key, Value&& value) && {
1210     this->add(std::forward<Key>(key), std::forward<Value>(value));
1211     return std::move(*this);
1212 }
1213 
1214 static const std::unique_ptr<Item> kEmptyItemPtr;
1215 
1216 template <typename Key,
1217           typename = std::enable_if_t<std::is_integral_v<Key> || std::is_enum_v<Key> ||
1218                                       details::is_text_type_v<Key>::value>>
1219 const std::unique_ptr<Item>& Map::get(Key key) const {
1220     auto keyItem = details::makeItem(key);
1221 
1222     if (mCanonicalized) {
1223         // It's sorted, so binary-search it.
1224         auto found = std::lower_bound(begin(), end(), keyItem.get(),
1225                                       [](const entry_type& entry, const Item* key) {
1226                                           return keyLess(entry.first.get(), key);
1227                                       });
1228         return (found == end() || *found->first != *keyItem) ? kEmptyItemPtr : found->second;
1229     } else {
1230         // Unsorted, do a linear search.
1231         auto found = std::find_if(
1232                 begin(), end(), [&](const entry_type& entry) { return *entry.first == *keyItem; });
1233         return found == end() ? kEmptyItemPtr : found->second;
1234     }
1235 }
1236 
1237 template <typename T>
1238 SemanticTag::SemanticTag(uint64_t value, T&& taggedItem)
1239     : mValue(value), mTaggedItem(details::makeItem(std::forward<T>(taggedItem))) {}
1240 
1241 }  // namespace cppbor
1242