blob: 0fcd1a003d23d7704a3dec7d53f3ffce7679bacb [file] [log] [blame]
Kim Paulhamus6efcf4952017-09-14 22:46:271// 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
Adam Langleye0e46cdf2018-10-29 19:23:165#ifndef COMPONENTS_CBOR_VALUES_H_
6#define COMPONENTS_CBOR_VALUES_H_
Kim Paulhamus6efcf4952017-09-14 22:46:277
Jun Choi06ae32d2017-12-21 18:52:398#include <stdint.h>
Jun Choi7b6fbff2018-01-22 19:54:019
Kim Paulhamus6efcf4952017-09-14 22:46:2710#include <string>
Adam Langley68672fd2017-10-17 19:35:2711#include <tuple>
Kim Paulhamus6efcf4952017-09-14 22:46:2712#include <vector>
13
14#include "base/containers/flat_map.h"
jdoerrieb5384422018-06-14 21:22:1915#include "base/containers/span.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2716#include "base/macros.h"
Adam Langleydf763d792017-11-28 19:20:1517#include "base/strings/string_piece.h"
Jun Choi9f1446c02017-12-21 23:33:2718#include "components/cbor/cbor_export.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2719
Jun Choi9f1446c02017-12-21 23:33:2720namespace cbor {
Kim Paulhamus6efcf4952017-09-14 22:46:2721
22// A class for Concise Binary Object Representation (CBOR) values.
23// This does not support:
Kim Paulhamus6efcf4952017-09-14 22:46:2724// * Floating-point numbers.
25// * Indefinite-length encodings.
Adam Langleyb4f12f92018-10-26 21:00:0226class CBOR_EXPORT Value {
Kim Paulhamus6efcf4952017-09-14 22:46:2727 public:
Kouhei Ueno6d1629e2018-02-01 17:28:0328 struct Less {
Adam Langley68672fd2017-10-17 19:35:2729 // Comparison predicate to order keys in a dictionary as required by the
Kouhei Ueno6d1629e2018-02-01 17:28:0330 // canonical CBOR order defined in
31 // https://tools.ietf.org/html/rfc7049#section-3.9
32 // TODO(808022): Clarify where this stands.
Adam Langleyb4f12f92018-10-26 21:00:0233 bool operator()(const Value& a, const Value& b) const {
Tsuyoshi Horo2a1fd522020-01-14 09:18:5134 // The current implementation only supports integer, text string, byte
35 // string and invalid UTF8 keys.
36 DCHECK((a.is_integer() || a.is_string() || a.is_bytestring() ||
37 a.is_invalid_utf8()) &&
38 (b.is_integer() || b.is_string() || b.is_bytestring() ||
39 b.is_invalid_utf8()));
Kouhei Ueno6d1629e2018-02-01 17:28:0340
41 // Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
42 // * If the major types are different, the one with the lower value
43 // in numerical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0944 if (a.type() != b.type())
45 return a.type() < b.type();
Kouhei Ueno6d1629e2018-02-01 17:28:0346
47 // * If two keys have different lengths, the shorter one sorts
48 // earlier;
49 // * If two keys have the same length, the one with the lower value
50 // in (byte-wise) lexical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0951 switch (a.type()) {
52 case Type::UNSIGNED:
Kouhei Ueno6d1629e2018-02-01 17:28:0353 // For unsigned integers, the smaller value has shorter length,
54 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3955 return a.GetInteger() < b.GetInteger();
56 case Type::NEGATIVE:
Kouhei Ueno6d1629e2018-02-01 17:28:0357 // For negative integers, the value closer to zero has shorter length,
58 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3959 return a.GetInteger() > b.GetInteger();
Jun Choi98a59e462017-12-14 23:04:0960 case Type::STRING: {
61 const auto& a_str = a.GetString();
62 const size_t a_length = a_str.size();
63 const auto& b_str = b.GetString();
64 const size_t b_length = b_str.size();
65 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
66 }
Kouhei Ueno6d1629e2018-02-01 17:28:0367 case Type::BYTE_STRING: {
68 const auto& a_str = a.GetBytestring();
69 const size_t a_length = a_str.size();
70 const auto& b_str = b.GetBytestring();
71 const size_t b_length = b_str.size();
72 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
73 }
Tsuyoshi Horo2a1fd522020-01-14 09:18:5174 case Type::INVALID_UTF8: {
75 const auto& a_str = a.GetInvalidUTF8();
76 const size_t a_length = a_str.size();
77 const auto& b_str = b.GetInvalidUTF8();
78 const size_t b_length = b_str.size();
79 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
80 }
Jun Choi98a59e462017-12-14 23:04:0981 default:
82 break;
83 }
84
85 NOTREACHED();
86 return false;
Adam Langley68672fd2017-10-17 19:35:2787 }
88
Adam Langley68672fd2017-10-17 19:35:2789 using is_transparent = void;
90 };
91
Kim Paulhamus6efcf4952017-09-14 22:46:2792 using BinaryValue = std::vector<uint8_t>;
Adam Langleyb4f12f92018-10-26 21:00:0293 using ArrayValue = std::vector<Value>;
94 using MapValue = base::flat_map<Value, Value, Less>;
Kim Paulhamus6efcf4952017-09-14 22:46:2795
96 enum class Type {
Jun Choi6d30c4a2017-12-09 01:10:3297 UNSIGNED = 0,
Jun Choi06ae32d2017-12-21 18:52:3998 NEGATIVE = 1,
Jun Choi6d30c4a2017-12-09 01:10:3299 BYTE_STRING = 2,
100 STRING = 3,
101 ARRAY = 4,
102 MAP = 5,
Chris Palmerbe2d8dc2018-09-14 00:31:42103 TAG = 6,
Jun Choi07540c62017-12-21 02:51:43104 SIMPLE_VALUE = 7,
Jun Choi6d30c4a2017-12-09 01:10:32105 NONE = -1,
Adam Langley08718f732019-04-22 22:21:33106 INVALID_UTF8 = -2,
Kim Paulhamus6efcf4952017-09-14 22:46:27107 };
108
Jun Choi07540c62017-12-21 02:51:43109 enum class SimpleValue {
110 FALSE_VALUE = 20,
111 TRUE_VALUE = 21,
112 NULL_VALUE = 22,
113 UNDEFINED = 23,
114 };
115
Martin Kreichgauer2344a642019-07-15 21:32:50116 // Returns a Value with Type::INVALID_UTF8. This factory method lets tests
117 // encode such a value as a CBOR string. It should never be used outside of
118 // tests since encoding may yield invalid CBOR data.
119 static Value InvalidUTF8StringValueForTesting(base::StringPiece in_string);
120
Adam Langleyb4f12f92018-10-26 21:00:02121 Value(Value&& that) noexcept;
122 Value() noexcept; // A NONE value.
Kim Paulhamus6efcf4952017-09-14 22:46:27123
Adam Langleyb4f12f92018-10-26 21:00:02124 explicit Value(Type type);
Jun Choi7b6fbff2018-01-22 19:54:01125
Adam Langleyb4f12f92018-10-26 21:00:02126 explicit Value(SimpleValue in_simple);
127 explicit Value(bool boolean_value);
Jun Choi7b6fbff2018-01-22 19:54:01128
Adam Langleyb4f12f92018-10-26 21:00:02129 explicit Value(int integer_value);
130 explicit Value(int64_t integer_value);
131 explicit Value(uint64_t integer_value) = delete;
Kim Paulhamus6efcf4952017-09-14 22:46:27132
Adam Langleyb4f12f92018-10-26 21:00:02133 explicit Value(base::span<const uint8_t> in_bytes);
134 explicit Value(BinaryValue&& in_bytes) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27135
Adam Langleyb4f12f92018-10-26 21:00:02136 explicit Value(const char* in_string, Type type = Type::STRING);
137 explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept;
138 explicit Value(base::StringPiece in_string, Type type = Type::STRING);
Kim Paulhamus6efcf4952017-09-14 22:46:27139
Adam Langleyb4f12f92018-10-26 21:00:02140 explicit Value(const ArrayValue& in_array);
141 explicit Value(ArrayValue&& in_array) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27142
Adam Langleyb4f12f92018-10-26 21:00:02143 explicit Value(const MapValue& in_map);
144 explicit Value(MapValue&& in_map) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27145
Adam Langleyb4f12f92018-10-26 21:00:02146 Value& operator=(Value&& that) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27147
Adam Langleyb4f12f92018-10-26 21:00:02148 ~Value();
Kim Paulhamus6efcf4952017-09-14 22:46:27149
Adam Langleyb4f12f92018-10-26 21:00:02150 // Value's copy constructor and copy assignment operator are deleted.
Kim Paulhamus6efcf4952017-09-14 22:46:27151 // Use this to obtain a deep copy explicitly.
Adam Langleyb4f12f92018-10-26 21:00:02152 Value Clone() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27153
154 // Returns the type of the value stored by the current Value object.
155 Type type() const { return type_; }
156
157 // Returns true if the current object represents a given type.
158 bool is_type(Type type) const { return type == type_; }
159 bool is_none() const { return type() == Type::NONE; }
Adam Langley08718f732019-04-22 22:21:33160 bool is_invalid_utf8() const { return type() == Type::INVALID_UTF8; }
Jun Choi7b6fbff2018-01-22 19:54:01161 bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
162 bool is_bool() const {
163 return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
164 simple_value_ == SimpleValue::FALSE_VALUE);
165 }
Kim Paulhamus6efcf4952017-09-14 22:46:27166 bool is_unsigned() const { return type() == Type::UNSIGNED; }
Jun Choi06ae32d2017-12-21 18:52:39167 bool is_negative() const { return type() == Type::NEGATIVE; }
168 bool is_integer() const { return is_unsigned() || is_negative(); }
Jun Choi6d30c4a2017-12-09 01:10:32169 bool is_bytestring() const { return type() == Type::BYTE_STRING; }
Kim Paulhamus6efcf4952017-09-14 22:46:27170 bool is_string() const { return type() == Type::STRING; }
171 bool is_array() const { return type() == Type::ARRAY; }
172 bool is_map() const { return type() == Type::MAP; }
173
174 // These will all fatally assert if the type doesn't match.
Jun Choi07540c62017-12-21 02:51:43175 SimpleValue GetSimpleValue() const;
Jun Choi7b6fbff2018-01-22 19:54:01176 bool GetBool() const;
Jun Choi06ae32d2017-12-21 18:52:39177 const int64_t& GetInteger() const;
178 const int64_t& GetUnsigned() const;
179 const int64_t& GetNegative() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27180 const BinaryValue& GetBytestring() const;
Kouhei Uenoc12b0b92018-02-01 14:02:10181 base::StringPiece GetBytestringAsString() const;
Jun Choi47be22c2017-12-14 07:55:16182 // Returned string may contain NUL characters.
Kim Paulhamus6efcf4952017-09-14 22:46:27183 const std::string& GetString() const;
184 const ArrayValue& GetArray() const;
185 const MapValue& GetMap() const;
Adam Langley08718f732019-04-22 22:21:33186 const BinaryValue& GetInvalidUTF8() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27187
188 private:
Adam Langley08718f732019-04-22 22:21:33189 friend class Reader;
190 // This constructor allows INVALID_UTF8 values to be created, which only
Martin Kreichgauer2344a642019-07-15 21:32:50191 // |Reader| and InvalidUTF8StringValueForTesting() may do.
Adam Langley08718f732019-04-22 22:21:33192 Value(base::span<const uint8_t> in_bytes, Type type);
193
Kim Paulhamus6efcf4952017-09-14 22:46:27194 Type type_;
195
196 union {
Jun Choi07540c62017-12-21 02:51:43197 SimpleValue simple_value_;
Jun Choi06ae32d2017-12-21 18:52:39198 int64_t integer_value_;
Daniel Cheng9eb43fd342017-10-10 21:28:37199 BinaryValue bytestring_value_;
200 std::string string_value_;
201 ArrayValue array_value_;
202 MapValue map_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27203 };
204
Adam Langleyb4f12f92018-10-26 21:00:02205 void InternalMoveConstructFrom(Value&& that);
Kim Paulhamus6efcf4952017-09-14 22:46:27206 void InternalCleanup();
207
Adam Langleyb4f12f92018-10-26 21:00:02208 DISALLOW_COPY_AND_ASSIGN(Value);
Kim Paulhamus6efcf4952017-09-14 22:46:27209};
Martin Kreichgauer2344a642019-07-15 21:32:50210
Jun Choi9f1446c02017-12-21 23:33:27211} // namespace cbor
Kim Paulhamus6efcf4952017-09-14 22:46:27212
Adam Langleye0e46cdf2018-10-29 19:23:16213#endif // COMPONENTS_CBOR_VALUES_H_