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