blob: 46a9508ed5dfcc7583d893b1d8a4681a7fb32dc6 [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>
Helmut Januschka26faf712024-05-01 20:04:4811#include <string_view>
Adam Langley68672fd2017-10-17 19:35:2712#include <tuple>
Kim Paulhamus6efcf4952017-09-14 22:46:2713#include <vector>
14
Hans Wennborg29c74d3f2020-06-24 13:46:3515#include "base/check.h"
Kim Paulhamus6efcf4952017-09-14 22:46:2716#include "base/containers/flat_map.h"
jdoerrieb5384422018-06-14 21:22:1917#include "base/containers/span.h"
Hans Wennborg29c74d3f2020-06-24 13:46:3518#include "base/notreached.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.
Matt Menke38aa28bb2024-06-27 19:26:1824// This does not support indefinite-length encodings.
Adam Langleyb4f12f92018-10-26 21:00:0225class CBOR_EXPORT Value {
Kim Paulhamus6efcf4952017-09-14 22:46:2726 public:
Kouhei Ueno6d1629e2018-02-01 17:28:0327 struct Less {
Adam Langley68672fd2017-10-17 19:35:2728 // Comparison predicate to order keys in a dictionary as required by the
Kouhei Ueno6d1629e2018-02-01 17:28:0329 // canonical CBOR order defined in
30 // https://tools.ietf.org/html/rfc7049#section-3.9
Alison Galeb8be9522024-04-16 00:00:3131 // TODO(crbug.com/40560917): Clarify where this stands.
Adam Langleyb4f12f92018-10-26 21:00:0232 bool operator()(const Value& a, const Value& b) const {
Tsuyoshi Horo2a1fd522020-01-14 09:18:5133 // The current implementation only supports integer, text string, byte
34 // string and invalid UTF8 keys.
35 DCHECK((a.is_integer() || a.is_string() || a.is_bytestring() ||
36 a.is_invalid_utf8()) &&
37 (b.is_integer() || b.is_string() || b.is_bytestring() ||
38 b.is_invalid_utf8()));
Kouhei Ueno6d1629e2018-02-01 17:28:0339
40 // Below text from https://tools.ietf.org/html/rfc7049 errata 4409:
41 // * If the major types are different, the one with the lower value
42 // in numerical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0943 if (a.type() != b.type())
44 return a.type() < b.type();
Kouhei Ueno6d1629e2018-02-01 17:28:0345
46 // * If two keys have different lengths, the shorter one sorts
47 // earlier;
48 // * If two keys have the same length, the one with the lower value
49 // in (byte-wise) lexical order sorts earlier.
Jun Choi98a59e462017-12-14 23:04:0950 switch (a.type()) {
51 case Type::UNSIGNED:
Kouhei Ueno6d1629e2018-02-01 17:28:0352 // For unsigned integers, the smaller value has shorter length,
53 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3954 return a.GetInteger() < b.GetInteger();
55 case Type::NEGATIVE:
Kouhei Ueno6d1629e2018-02-01 17:28:0356 // For negative integers, the value closer to zero has shorter length,
57 // and (byte-wise) lexical representation.
Jun Choi06ae32d2017-12-21 18:52:3958 return a.GetInteger() > b.GetInteger();
Jun Choi98a59e462017-12-14 23:04:0959 case Type::STRING: {
60 const auto& a_str = a.GetString();
61 const size_t a_length = a_str.size();
62 const auto& b_str = b.GetString();
63 const size_t b_length = b_str.size();
64 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
65 }
Kouhei Ueno6d1629e2018-02-01 17:28:0366 case Type::BYTE_STRING: {
67 const auto& a_str = a.GetBytestring();
68 const size_t a_length = a_str.size();
69 const auto& b_str = b.GetBytestring();
70 const size_t b_length = b_str.size();
71 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
72 }
Tsuyoshi Horo2a1fd522020-01-14 09:18:5173 case Type::INVALID_UTF8: {
74 const auto& a_str = a.GetInvalidUTF8();
75 const size_t a_length = a_str.size();
76 const auto& b_str = b.GetInvalidUTF8();
77 const size_t b_length = b_str.size();
78 return std::tie(a_length, a_str) < std::tie(b_length, b_str);
79 }
Jun Choi98a59e462017-12-14 23:04:0980 default:
81 break;
82 }
83
Peter Boström77d21352024-11-13 22:26:1184 NOTREACHED();
Adam Langley68672fd2017-10-17 19:35:2785 }
86
Adam Langley68672fd2017-10-17 19:35:2787 using is_transparent = void;
88 };
89
Kim Paulhamus6efcf4952017-09-14 22:46:2790 using BinaryValue = std::vector<uint8_t>;
Adam Langleyb4f12f92018-10-26 21:00:0291 using ArrayValue = std::vector<Value>;
92 using MapValue = base::flat_map<Value, Value, Less>;
Kim Paulhamus6efcf4952017-09-14 22:46:2793
94 enum class Type {
Jun Choi6d30c4a2017-12-09 01:10:3295 UNSIGNED = 0,
Jun Choi06ae32d2017-12-21 18:52:3996 NEGATIVE = 1,
Jun Choi6d30c4a2017-12-09 01:10:3297 BYTE_STRING = 2,
98 STRING = 3,
99 ARRAY = 4,
100 MAP = 5,
Chris Palmerbe2d8dc2018-09-14 00:31:42101 TAG = 6,
Jun Choi07540c62017-12-21 02:51:43102 SIMPLE_VALUE = 7,
Russ Hamilton385541b2023-07-06 00:30:38103 // In CBOR floating types also have major type 7, but we separate them here
104 // for simplicity.
105 FLOAT_VALUE = 70,
Jun Choi6d30c4a2017-12-09 01:10:32106 NONE = -1,
Adam Langley08718f732019-04-22 22:21:33107 INVALID_UTF8 = -2,
Kim Paulhamus6efcf4952017-09-14 22:46:27108 };
109
Jun Choi07540c62017-12-21 02:51:43110 enum class SimpleValue {
111 FALSE_VALUE = 20,
112 TRUE_VALUE = 21,
113 NULL_VALUE = 22,
114 UNDEFINED = 23,
115 };
116
Martin Kreichgauer2344a642019-07-15 21:32:50117 // Returns a Value with Type::INVALID_UTF8. This factory method lets tests
118 // encode such a value as a CBOR string. It should never be used outside of
119 // tests since encoding may yield invalid CBOR data.
Helmut Januschka26faf712024-05-01 20:04:48120 static Value InvalidUTF8StringValueForTesting(std::string_view in_string);
Martin Kreichgauer2344a642019-07-15 21:32:50121
Adam Langleyb4f12f92018-10-26 21:00:02122 Value(Value&& that) noexcept;
123 Value() noexcept; // A NONE value.
Kim Paulhamus6efcf4952017-09-14 22:46:27124
Adam Langleyb4f12f92018-10-26 21:00:02125 explicit Value(Type type);
Jun Choi7b6fbff2018-01-22 19:54:01126
Adam Langleyb4f12f92018-10-26 21:00:02127 explicit Value(SimpleValue in_simple);
128 explicit Value(bool boolean_value);
Russ Hamilton385541b2023-07-06 00:30:38129 explicit Value(double in_float);
Jun Choi7b6fbff2018-01-22 19:54:01130
Adam Langleyb4f12f92018-10-26 21:00:02131 explicit Value(int integer_value);
132 explicit Value(int64_t integer_value);
133 explicit Value(uint64_t integer_value) = delete;
Kim Paulhamus6efcf4952017-09-14 22:46:27134
Adam Langleyb4f12f92018-10-26 21:00:02135 explicit Value(base::span<const uint8_t> in_bytes);
136 explicit Value(BinaryValue&& in_bytes) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27137
Adam Langleyb4f12f92018-10-26 21:00:02138 explicit Value(const char* in_string, Type type = Type::STRING);
139 explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept;
Helmut Januschka26faf712024-05-01 20:04:48140 explicit Value(std::string_view in_string, Type type = Type::STRING);
Kim Paulhamus6efcf4952017-09-14 22:46:27141
Adam Langleyb4f12f92018-10-26 21:00:02142 explicit Value(const ArrayValue& in_array);
143 explicit Value(ArrayValue&& in_array) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27144
Adam Langleyb4f12f92018-10-26 21:00:02145 explicit Value(const MapValue& in_map);
146 explicit Value(MapValue&& in_map) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27147
Adam Langleyb4f12f92018-10-26 21:00:02148 Value& operator=(Value&& that) noexcept;
Kim Paulhamus6efcf4952017-09-14 22:46:27149
Peter Boström09c01822021-09-20 22:43:27150 Value(const Value&) = delete;
151 Value& operator=(const Value&) = delete;
152
Adam Langleyb4f12f92018-10-26 21:00:02153 ~Value();
Kim Paulhamus6efcf4952017-09-14 22:46:27154
Adam Langleyb4f12f92018-10-26 21:00:02155 // Value's copy constructor and copy assignment operator are deleted.
Kim Paulhamus6efcf4952017-09-14 22:46:27156 // Use this to obtain a deep copy explicitly.
Adam Langleyb4f12f92018-10-26 21:00:02157 Value Clone() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27158
159 // Returns the type of the value stored by the current Value object.
160 Type type() const { return type_; }
161
162 // Returns true if the current object represents a given type.
163 bool is_type(Type type) const { return type == type_; }
164 bool is_none() const { return type() == Type::NONE; }
Adam Langley08718f732019-04-22 22:21:33165 bool is_invalid_utf8() const { return type() == Type::INVALID_UTF8; }
Jun Choi7b6fbff2018-01-22 19:54:01166 bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
167 bool is_bool() const {
168 return is_simple() && (simple_value_ == SimpleValue::TRUE_VALUE ||
169 simple_value_ == SimpleValue::FALSE_VALUE);
170 }
Russ Hamilton385541b2023-07-06 00:30:38171 bool is_double() const { return type() == Type::FLOAT_VALUE; }
Kim Paulhamus6efcf4952017-09-14 22:46:27172 bool is_unsigned() const { return type() == Type::UNSIGNED; }
Jun Choi06ae32d2017-12-21 18:52:39173 bool is_negative() const { return type() == Type::NEGATIVE; }
174 bool is_integer() const { return is_unsigned() || is_negative(); }
Jun Choi6d30c4a2017-12-09 01:10:32175 bool is_bytestring() const { return type() == Type::BYTE_STRING; }
Kim Paulhamus6efcf4952017-09-14 22:46:27176 bool is_string() const { return type() == Type::STRING; }
177 bool is_array() const { return type() == Type::ARRAY; }
178 bool is_map() const { return type() == Type::MAP; }
179
180 // These will all fatally assert if the type doesn't match.
Jun Choi07540c62017-12-21 02:51:43181 SimpleValue GetSimpleValue() const;
Jun Choi7b6fbff2018-01-22 19:54:01182 bool GetBool() const;
Russ Hamilton385541b2023-07-06 00:30:38183 double GetDouble() const;
Jun Choi06ae32d2017-12-21 18:52:39184 const int64_t& GetInteger() const;
185 const int64_t& GetUnsigned() const;
186 const int64_t& GetNegative() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27187 const BinaryValue& GetBytestring() const;
Helmut Januschka26faf712024-05-01 20:04:48188 std::string_view GetBytestringAsString() const;
Jun Choi47be22c2017-12-14 07:55:16189 // Returned string may contain NUL characters.
Kim Paulhamus6efcf4952017-09-14 22:46:27190 const std::string& GetString() const;
191 const ArrayValue& GetArray() const;
192 const MapValue& GetMap() const;
Adam Langley08718f732019-04-22 22:21:33193 const BinaryValue& GetInvalidUTF8() const;
Kim Paulhamus6efcf4952017-09-14 22:46:27194
195 private:
Adam Langley08718f732019-04-22 22:21:33196 friend class Reader;
197 // This constructor allows INVALID_UTF8 values to be created, which only
Martin Kreichgauer2344a642019-07-15 21:32:50198 // |Reader| and InvalidUTF8StringValueForTesting() may do.
Adam Langley08718f732019-04-22 22:21:33199 Value(base::span<const uint8_t> in_bytes, Type type);
200
Kim Paulhamus6efcf4952017-09-14 22:46:27201 Type type_;
202
203 union {
Jun Choi07540c62017-12-21 02:51:43204 SimpleValue simple_value_;
Jun Choi06ae32d2017-12-21 18:52:39205 int64_t integer_value_;
Russ Hamilton385541b2023-07-06 00:30:38206 double float_value_;
Daniel Cheng9eb43fd342017-10-10 21:28:37207 BinaryValue bytestring_value_;
208 std::string string_value_;
209 ArrayValue array_value_;
210 MapValue map_value_;
Kim Paulhamus6efcf4952017-09-14 22:46:27211 };
212
Adam Langleyb4f12f92018-10-26 21:00:02213 void InternalMoveConstructFrom(Value&& that);
Kim Paulhamus6efcf4952017-09-14 22:46:27214 void InternalCleanup();
Kim Paulhamus6efcf4952017-09-14 22:46:27215};
Martin Kreichgauer2344a642019-07-15 21:32:50216
Jun Choi9f1446c02017-12-21 23:33:27217} // namespace cbor
Kim Paulhamus6efcf4952017-09-14 22:46:27218
Adam Langleye0e46cdf2018-10-29 19:23:16219#endif // COMPONENTS_CBOR_VALUES_H_