1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_CBOR_WRITER_H_ 6 #define COMPONENTS_CBOR_WRITER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <vector> 12 13 #include "base/optional.h" 14 #include "components/cbor/cbor_export.h" 15 #include "components/cbor/values.h" 16 17 // A basic Concise Binary Object Representation (CBOR) encoder as defined by 18 // https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies 19 // canonical, well-formed CBOR values but does not guarantee their validity 20 // (see https://tools.ietf.org/html/rfc7049#section-3.2). 21 // Supported: 22 // * Major types: 23 // * 0: Unsigned integers, up to INT64_MAX. 24 // * 1: Negative integers, to INT64_MIN. 25 // * 2: Byte strings. 26 // * 3: UTF-8 strings. 27 // * 4: Arrays, with the number of elements known at the start. 28 // * 5: Maps, with the number of elements known at the start 29 // of the container. 30 // * 7: Simple values. 31 // 32 // Unsupported: 33 // * Floating-point numbers. 34 // * Indefinite-length encodings. 35 // * Parsing. 36 // 37 // Requirements for canonical CBOR as suggested by RFC 7049 are: 38 // 1) All major data types for the CBOR values must be as short as possible. 39 // * Unsigned integer between 0 to 23 must be expressed in same byte as 40 // the major type. 41 // * 24 to 255 must be expressed only with an additional uint8_t. 42 // * 256 to 65535 must be expressed only with an additional uint16_t. 43 // * 65536 to 4294967295 must be expressed only with an additional 44 // uint32_t. * The rules for expression of length in major types 45 // 2 to 5 follow the above rule for integers. 46 // 2) Keys in every map must be sorted (first by major type, then by key 47 // length, then by value in byte-wise lexical order). 48 // 3) Indefinite length items must be converted to definite length items. 49 // 4) All maps must not have duplicate keys. 50 // 51 // Current implementation of Writer encoder meets all the requirements of 52 // canonical CBOR. 53 54 namespace cbor { 55 56 class CBOR_EXPORT Writer { 57 public: 58 // Default that should be sufficiently large for most use cases. 59 static constexpr size_t kDefaultMaxNestingDepth = 16; 60 61 struct CBOR_EXPORT Config { 62 // Controls the maximum depth of CBOR nesting that will be permitted in a 63 // Value. Nesting depth is defined as the number of arrays/maps that have to 64 // be traversed to reach the most nested contained Value. Primitive values 65 // and empty containers have nesting depths of 0. 66 int max_nesting_level = kDefaultMaxNestingDepth; 67 68 // Controls whether the Writer allows writing string values of type 69 // Value::Type::INVALID_UTF8. Regular CBOR strings must be valid UTF-8. 70 // Writers with this setting will produce invalid CBOR, so it may only be 71 // enabled in tests. 72 bool allow_invalid_utf8_for_testing = false; 73 }; 74 75 ~Writer(); 76 77 // Returns the CBOR byte string representation of |node|, unless its nesting 78 // depth is greater than |max_nesting_level|, in which case an empty optional 79 // value is returned. 80 static base::Optional<std::vector<uint8_t>> Write( 81 const Value& node, 82 size_t max_nesting_level = kDefaultMaxNestingDepth); 83 84 // A version of |Write| above that takes a Config. 85 static base::Optional<std::vector<uint8_t>> Write(const Value& node, 86 const Config& config); 87 88 private: 89 explicit Writer(std::vector<uint8_t>* cbor); 90 91 // Called recursively to build the CBOR bytestring. When completed, 92 // |encoded_cbor_| will contain the CBOR. 93 bool EncodeCBOR(const Value& node, 94 int max_nesting_level, 95 bool allow_invalid_utf8); 96 97 // Encodes the type and size of the data being added. 98 void StartItem(Value::Type type, uint64_t size); 99 100 // Encodes the additional information for the data. 101 void SetAdditionalInformation(uint8_t additional_information); 102 103 // Encodes an unsigned integer value. This is used to both write 104 // unsigned integers and to encode the lengths of other major types. 105 void SetUint(uint64_t value); 106 107 // Returns the number of bytes needed to store the unsigned integer. 108 size_t GetNumUintBytes(uint64_t value); 109 110 // Holds the encoded CBOR data. 111 std::vector<uint8_t>* encoded_cbor_; 112 113 DISALLOW_COPY_AND_ASSIGN(Writer); 114 }; 115 116 } // namespace cbor 117 118 #endif // COMPONENTS_CBOR_WRITER_H_ 119