blob: d81ef5607c55aba9eb977f6b1720d208d3f047d2 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2017 The Chromium Authors
Kim Paulhamus6efcf4952017-09-14 22:46:272// 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
Hans Wennborg29c74d3f2020-06-24 13:46:3514#include "base/check.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2715#include "base/containers/flat_map.h"
jdoerrieb5384422018-06-14 21:22:1916#include "base/containers/span.h"
Hans Wennborg29c74d3f2020-06-24 13:46:3517#include "base/notreached.h"
Adam Langleydf763d792017-11-28 19:20:1518#include "base/strings/string_piece.h"
Jun Choi9f1446c02017-12-21 23:33:2719#include "components/cbor/cbor_export.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2720
Jun Choi9f1446c02017-12-21 23:33:2721namespace cbor {
Kim Paulhamus6efcf4952017-09-14 22:46:2722
23// A class for Concise Binary Object Representation (CBOR) values.
24// This does not support:
Kim Paulhamus6efcf4952017-09-14 22:46:2725// * Floating-point numbers.
26// * Indefinite-length encodings.
Adam Langleyb4f12f92018-10-26 21:00:0227class CBOR_EXPORT Value {
Kim Paulhamus6efcf4952017-09-14 22:46:2728 public:
Kouhei Ueno6d1629e2018-02-01 17:28:0329 struct Less {
Adam Langley68672fd2017-10-17 19:35:2730 // Comparison predicate to order keys in a dictionary as required by the
Kouhei Ueno6d1629e2018-02-01 17:28:0331 // canonical CBOR order defined in
32 // https://tools.ietf.org/html/rfc7049#section-3.9
33 // TODO(808022): Clarify where this stands.
Adam Langleyb4f12f92018-10-26 21:00:0234 bool operator()(const Value& a, const Value& b) const {
Tsuyoshi Horo2a1fd522020-01-14 09:18:5135 // The current implementation only supports integer, text string, byte
36 // string and invalid UTF8 keys.
37 DCHECK((a.is_integer() || a.is_string() || a.is_bytestring() ||
38 a.is_invalid_utf8()) &&
39 (b.is_integer() || b.is_string() || b.is_bytestring() ||
40 b.is_invalid_utf8()));
Kouhei Ueno6d1629e2018-02-01 17:28:0341
42 // Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
43 // * If the major types are different, the one with the lower value
44 // in numerical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0945 if (a.type() != b.type())
46 return a.type() < b.type();
Kouhei Ueno6d1629e2018-02-01 17:28:0347
48 // * If two keys have different lengths, the shorter one sorts
49 // earlier;
50 // * If two keys have the same length, the one with the lower value
51 // in (byte-wise) lexical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0952 switch (a.type()) {
53 case Type::UNSIGNED:
Kouhei Ueno6d1629e2018-02-01 17:28:0354 // For unsigned integers, the smaller value has shorter length,
55 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3956 return a.GetInteger() < b.GetInteger();
57 case Type::NEGATIVE:
Kouhei Ueno6d1629e2018-02-01 17:28:0358 // For negative integers, the value closer to zero has shorter length,
59 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3960 return a.GetInteger() > b.GetInteger();
Jun Choi98a59e462017-12-14 23:04:0961 case Type::STRING: {
62 const auto& a_str = a.GetString();
63 const size_t a_length = a_str.size();
64 const auto& b_str = b.GetString();
65 const size_t b_length = b_str.size();
66 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
67 }
Kouhei Ueno6d1629e2018-02-01 17:28:0368 case Type::BYTE_STRING: {
69 const auto& a_str = a.GetBytestring();
70 const size_t a_length = a_str.size();
71 const auto& b_str = b.GetBytestring();
72 const size_t b_length = b_str.size();
73 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
74 }
Tsuyoshi Horo2a1fd522020-01-14 09:18:5175 case Type::INVALID_UTF8: {
76 const auto& a_str = a.GetInvalidUTF8();
77 const size_t a_length = a_str.size();
78 const auto& b_str = b.GetInvalidUTF8();
79 const size_t b_length = b_str.size();
80 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
81 }
Jun Choi98a59e462017-12-14 23:04:0982 default:
83 break;
84 }
85
86 NOTREACHED();
87 return false;
Adam Langley68672fd2017-10-17 19:35:2788 }
89
Adam Langley68672fd2017-10-17 19:35:2790 using is_transparent = void;
91 };
92
Kim Paulhamus6efcf4952017-09-14 22:46:2793 using BinaryValue = std::vector<uint8_t>;
Adam Langleyb4f12f92018-10-26 21:00:0294 using ArrayValue = std::vector<Value>;
95 using MapValue = base::flat_map<Value, Value, Less>;
Kim Paulhamus6efcf4952017-09-14 22:46:2796
97 enum class Type {
Jun Choi6d30c4a2017-12-09 01:10:3298 UNSIGNED = 0,
Jun Choi06ae32d2017-12-21 18:52:3999 NEGATIVE = 1,
Jun Choi6d30c4a2017-12-09 01:10:32100 BYTE_STRING = 2,
101 STRING = 3,
102 ARRAY = 4,
103 MAP = 5,
Chris Palmerbe2d8dc2018-09-14 00:31:42104 TAG = 6,
Jun Choi07540c62017-12-21 02:51:43105 SIMPLE_VALUE = 7,
Russ Hamilton385541b2023-07-06 00:30:38106 // In CBOR floating types also have major type 7, but we separate them here
107 // for simplicity.
108 FLOAT_VALUE = 70,
Jun Choi6d30c4a2017-12-09 01:10:32109 NONE = -1,
Adam Langley08718f732019-04-22 22:21:33110 INVALID_UTF8 = -2,
Kim Paulhamus6efcf4952017-09-14 22:46:27111 };
112
Jun Choi07540c62017-12-21 02:51:43113 enum class SimpleValue {
114 FALSE_VALUE = 20,
115 TRUE_VALUE = 21,
116 NULL_VALUE = 22,
117 UNDEFINED = 23,
118 };
119
Martin Kreichgauer2344a642019-07-15 21:32:50120 // Returns a Value with Type::INVALID_UTF8. This factory method lets tests
121 // encode such a value as a CBOR string. It should never be used outside of
122 // tests since encoding may yield invalid CBOR data.
123 static Value InvalidUTF8StringValueForTesting(base::StringPiece in_string);
124
Adam Langleyb4f12f92018-10-26 21:00:02125 Value(Value&& that) noexcept;
126 Value() noexcept; // A NONE value.
Kim Paulhamus6efcf4952017-09-14 22:46:27127
Adam Langleyb4f12f92018-10-26 21:00:02128 explicit Value(Type type);
Jun Choi7b6fbff2018-01-22 19:54:01129
Adam Langleyb4f12f92018-10-26 21:00:02130 explicit Value(SimpleValue in_simple);
131 explicit Value(bool boolean_value);
Russ Hamilton385541b2023-07-06 00:30:38132 explicit Value(double in_float);
Jun Choi7b6fbff2018-01-22 19:54:01133
Adam Langleyb4f12f92018-10-26 21:00:02134 explicit Value(int integer_value);
135 explicit Value(int64_t integer_value);
136 explicit Value(uint64_t integer_value) = delete;
Kim Paulhamus6efcf4952017-09-14 22:46:27137
Adam Langleyb4f12f92018-10-26 21:00:02138 explicit Value(base::span<const uint8_t> in_bytes);
139 explicit Value(BinaryValue&& in_bytes) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27140
Adam Langleyb4f12f92018-10-26 21:00:02141 explicit Value(const char* in_string, Type type = Type::STRING);
142 explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept;
143 explicit Value(base::StringPiece in_string, Type type = Type::STRING);
Kim Paulhamus6efcf4952017-09-14 22:46:27144
Adam Langleyb4f12f92018-10-26 21:00:02145 explicit Value(const ArrayValue& in_array);
146 explicit Value(ArrayValue&& in_array) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27147
Adam Langleyb4f12f92018-10-26 21:00:02148 explicit Value(const MapValue& in_map);
149 explicit Value(MapValue&& in_map) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27150
Adam Langleyb4f12f92018-10-26 21:00:02151 Value& operator=(Value&& that) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27152
Peter Boström09c01822021-09-20 22:43:27153 Value(const Value&) = delete;
154 Value& operator=(const Value&) = delete;
155
Adam Langleyb4f12f92018-10-26 21:00:02156 ~Value();
Kim Paulhamus6efcf4952017-09-14 22:46:27157
Adam Langleyb4f12f92018-10-26 21:00:02158 // Value's copy constructor and copy assignment operator are deleted.
Kim Paulhamus6efcf4952017-09-14 22:46:27159 // Use this to obtain a deep copy explicitly.
Adam Langleyb4f12f92018-10-26 21:00:02160 Value Clone() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27161
162 // Returns the type of the value stored by the current Value object.
163 Type type() const { return type_; }
164
165 // Returns true if the current object represents a given type.
166 bool is_type(Type type) const { return type == type_; }
167 bool is_none() const { return type() == Type::NONE; }
Adam Langley08718f732019-04-22 22:21:33168 bool is_invalid_utf8() const { return type() == Type::INVALID_UTF8; }
Jun Choi7b6fbff2018-01-22 19:54:01169 bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
170 bool is_bool() const {
171 return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
172 simple_value_ == SimpleValue::FALSE_VALUE);
173 }
Russ Hamilton385541b2023-07-06 00:30:38174 bool is_double() const { return type() == Type::FLOAT_VALUE; }
Kim Paulhamus6efcf4952017-09-14 22:46:27175 bool is_unsigned() const { return type() == Type::UNSIGNED; }
Jun Choi06ae32d2017-12-21 18:52:39176 bool is_negative() const { return type() == Type::NEGATIVE; }
177 bool is_integer() const { return is_unsigned() || is_negative(); }
Jun Choi6d30c4a2017-12-09 01:10:32178 bool is_bytestring() const { return type() == Type::BYTE_STRING; }
Kim Paulhamus6efcf4952017-09-14 22:46:27179 bool is_string() const { return type() == Type::STRING; }
180 bool is_array() const { return type() == Type::ARRAY; }
181 bool is_map() const { return type() == Type::MAP; }
182
183 // These will all fatally assert if the type doesn't match.
Jun Choi07540c62017-12-21 02:51:43184 SimpleValue GetSimpleValue() const;
Jun Choi7b6fbff2018-01-22 19:54:01185 bool GetBool() const;
Russ Hamilton385541b2023-07-06 00:30:38186 double GetDouble() const;
Jun Choi06ae32d2017-12-21 18:52:39187 const int64_t& GetInteger() const;
188 const int64_t& GetUnsigned() const;
189 const int64_t& GetNegative() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27190 const BinaryValue& GetBytestring() const;
Kouhei Uenoc12b0b92018-02-01 14:02:10191 base::StringPiece GetBytestringAsString() const;
Jun Choi47be22c2017-12-14 07:55:16192 // Returned string may contain NUL characters.
Kim Paulhamus6efcf4952017-09-14 22:46:27193 const std::string& GetString() const;
194 const ArrayValue& GetArray() const;
195 const MapValue& GetMap() const;
Adam Langley08718f732019-04-22 22:21:33196 const BinaryValue& GetInvalidUTF8() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27197
198 private:
Adam Langley08718f732019-04-22 22:21:33199 friend class Reader;
200 // This constructor allows INVALID_UTF8 values to be created, which only
Martin Kreichgauer2344a642019-07-15 21:32:50201 // |Reader| and InvalidUTF8StringValueForTesting() may do.
Adam Langley08718f732019-04-22 22:21:33202 Value(base::span<const uint8_t> in_bytes, Type type);
203
Kim Paulhamus6efcf4952017-09-14 22:46:27204 Type type_;
205
206 union {
Jun Choi07540c62017-12-21 02:51:43207 SimpleValue simple_value_;
Jun Choi06ae32d2017-12-21 18:52:39208 int64_t integer_value_;
Russ Hamilton385541b2023-07-06 00:30:38209 double float_value_;
Daniel Cheng9eb43fd342017-10-10 21:28:37210 BinaryValue bytestring_value_;
211 std::string string_value_;
212 ArrayValue array_value_;
213 MapValue map_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27214 };
215
Adam Langleyb4f12f92018-10-26 21:00:02216 void InternalMoveConstructFrom(Value&& that);
Kim Paulhamus6efcf4952017-09-14 22:46:27217 void InternalCleanup();
Kim Paulhamus6efcf4952017-09-14 22:46:27218};
Martin Kreichgauer2344a642019-07-15 21:32:50219
Jun Choi9f1446c02017-12-21 23:33:27220} // namespace cbor
Kim Paulhamus6efcf4952017-09-14 22:46:27221
Adam Langleye0e46cdf2018-10-29 19:23:16222#endif // COMPONENTS_CBOR_VALUES_H_