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