• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 BASE_VALUES_H_
6 #define BASE_VALUES_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <array>
12 #include <initializer_list>
13 #include <iosfwd>
14 #include <iterator>
15 #include <memory>
16 #include <optional>
17 #include <string>
18 #include <string_view>
19 #include <utility>
20 #include <vector>
21 
22 #include "base/base_export.h"
23 #include "base/bit_cast.h"
24 #include "base/compiler_specific.h"
25 #include "base/containers/checked_iterators.h"
26 #include "base/containers/flat_map.h"
27 #include "base/containers/span.h"
28 #include "base/memory/raw_ref.h"
29 #include "base/trace_event/base_tracing_forward.h"
30 #include "base/value_iterators.h"
31 #include "third_party/abseil-cpp/absl/types/variant.h"
32 
33 namespace base {
34 
35 // The `Value` class is a variant type can hold one of the following types:
36 // - null
37 // - bool
38 // - int
39 // - double
40 // - string (internally UTF8-encoded)
41 // - binary data (i.e. a blob)
42 // - dictionary of string keys to `Value`s
43 // - list of `Value`s
44 //
45 // With the exception of binary blobs, `Value` is intended to be the C++ version
46 // of data types that can be represented in JSON.
47 //
48 // Warning: blob support may be removed in the future.
49 //
50 // ## Usage
51 //
52 // Do not use `Value` if a more specific type would be more appropriate.  For
53 // example, a function that only accepts dictionary values should have a
54 // `base::Value::Dict` parameter, not a `base::Value` parameter.
55 //
56 // Construction:
57 //
58 // `Value` is directly constructible from `bool`, `int`, `double`, binary blobs
59 // (`std::vector<uint8_t>`), `std::string_view`, `std::u16string_view`,
60 // `Value::Dict`, and `Value::List`.
61 //
62 // Copying:
63 //
64 // `Value` does not support C++ copy semantics to make it harder to accidentally
65 // copy large values. Instead, use `Clone()` to manually create a deep copy.
66 //
67 // Reading:
68 //
69 // `GetBool()`, GetInt()`, et cetera `CHECK()` that the `Value` has the correct
70 // subtype before returning the contained value. `bool`, `int`, `double` are
71 // returned by value. Binary blobs, `std::string`, `Value::Dict`, `Value::List`
72 // are returned by reference.
73 //
74 // `GetIfBool()`, `GetIfInt()`, et cetera return `std::nullopt`/`nullptr` if
75 // the `Value` does not have the correct subtype; otherwise, returns the value
76 // wrapped in an `std::optional` (for `bool`, `int`, `double`) or by pointer
77 // (for binary blobs, `std::string`, `Value::Dict`, `Value::List`).
78 //
79 // Note: both `GetDouble()` and `GetIfDouble()` still return a non-null result
80 // when the subtype is `Value::Type::INT`. In that case, the stored value is
81 // coerced to a double before being returned.
82 //
83 // Assignment:
84 //
85 // It is not possible to directly assign `bool`, `int`, et cetera to a `Value`.
86 // Instead, wrap the underlying type in `Value` before assigning.
87 //
88 // ## Dictionaries and Lists
89 //
90 // `Value` provides the `Value::Dict` and `Value::List` container types for
91 // working with dictionaries and lists of values respectively, rather than
92 // exposing the underlying container types directly. This allows the types to
93 // provide convenient helpers for dictionaries and lists, as well as giving
94 // greater flexibility for changing implementation details in the future.
95 //
96 // Both container types support enough STL-isms to be usable in range-based for
97 // loops and generic operations such as those from <algorithm>.
98 //
99 // Dictionaries support:
100 // - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
101 //       `contains()`, `clear()`, `erase()`: Identical to the STL container
102 //       equivalents, with additional safety checks, e.g. iterators will
103 //       `CHECK()` if `end()` is dereferenced.
104 //
105 // - `Clone()`: Create a deep copy.
106 // - `Merge()`: Merge another dictionary into this dictionary.
107 // - `Find()`: Find a value by `std::string_view` key, returning nullptr if the
108 //       key is not present.
109 // - `FindBool()`, `FindInt()`, ...: Similar to `Find()`, but ensures that the
110 //       `Value` also has the correct subtype. Same return semantics as
111 //       `GetIfBool()`, `GetIfInt()`, et cetera, returning `std::nullopt` or
112 //       `nullptr` if the key is not present or the value has the wrong subtype.
113 // - `Set()`: Associate a value with a `std::string_view` key. Accepts `Value`
114 //       or any of the subtypes that `Value` can hold.
115 // - `Remove()`: Remove the key from this dictionary, if present.
116 // - `Extract()`: If the key is present in the dictionary, removes the key from
117 //       the dictionary and transfers ownership of `Value` to the caller.
118 //       Otherwise, returns `std::nullopt`.
119 //
120 // Dictionaries also support an additional set of helper methods that operate on
121 // "paths": `FindByDottedPath()`, `SetByDottedPath()`, `RemoveByDottedPath()`,
122 // and `ExtractByDottedPath()`. Dotted paths are a convenience method of naming
123 // intermediate nested dictionaries, separating the components of the path using
124 // '.' characters. For example, finding a string path on a `Value::Dict` using
125 // the dotted path:
126 //
127 //   "aaa.bbb.ccc"
128 //
129 // Will first look for a `Value::Type::DICT` associated with the key "aaa", then
130 // another `Value::Type::DICT` under the "aaa" dict associated with the
131 // key "bbb", and then a `Value::Type::STRING` under the "bbb" dict associated
132 // with the key "ccc".
133 //
134 // If a path only has one component (i.e. has no dots), please use the regular,
135 // non-path APIs.
136 //
137 // Lists support:
138 // - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
139 //       `rbegin()`, `rend()`, `front()`, `back()`, `reserve()`, `operator[]`,
140 //       `clear()`, `erase()`: Identical to the STL container equivalents, with
141 //       additional safety checks, e.g. `operator[]` will `CHECK()` if the index
142 //       is out of range.
143 // - `Clone()`: Create a deep copy.
144 // - `Append()`: Append a value to the end of the list. Accepts `Value` or any
145 //       of the subtypes that `Value` can hold.
146 // - `Insert()`: Insert a `Value` at a specified point in the list.
147 // - `EraseValue()`: Erases all matching `Value`s from the list.
148 // - `EraseIf()`: Erase all `Value`s matching an arbitrary predicate from the
149 //       list.
150 class BASE_EXPORT GSL_OWNER Value {
151  public:
152   using BlobStorage = std::vector<uint8_t>;
153 
154   class Dict;
155   class List;
156 
157   enum class Type : unsigned char {
158     NONE = 0,
159     BOOLEAN,
160     INTEGER,
161     DOUBLE,
162     STRING,
163     BINARY,
164     DICT,
165     LIST,
166     // Note: Do not add more types. See the file-level comment above for why.
167   };
168 
169   // Adaptors for converting from the old way to the new way and vice versa.
170   static Value FromUniquePtrValue(std::unique_ptr<Value> val);
171   static std::unique_ptr<Value> ToUniquePtrValue(Value val);
172 
173   Value() noexcept;
174 
175   Value(Value&&) noexcept;
176   Value& operator=(Value&&) noexcept;
177 
178   // Deleted to prevent accidental copying.
179   Value(const Value&) = delete;
180   Value& operator=(const Value&) = delete;
181 
182   // Creates a deep copy of this value.
183   Value Clone() const;
184 
185   // Creates a `Value` of `type`. The data of the corresponding type will be
186   // default constructed.
187   explicit Value(Type type);
188 
189   // Constructor for `Value::Type::BOOLEAN`.
190   explicit Value(bool value);
191 
192   // Prevent pointers from implicitly converting to bool. Another way to write
193   // this would be to template the bool constructor and use SFINAE to only allow
194   // use if `std::is_same_v<T, bool>` is true, but this has surprising behavior
195   // with range-based for loops over a `std::vector<bool>` (which will
196   // unintuitively match the int overload instead).
197   //
198   // The `const` is load-bearing; otherwise, a `char*` argument would prefer the
199   // deleted overload due to requiring a qualification conversion.
200   template <typename T>
201   explicit Value(const T*) = delete;
202 
203   // Constructor for `Value::Type::INT`.
204   explicit Value(int value);
205 
206   // Constructor for `Value::Type::DOUBLE`.
207   explicit Value(double value);
208 
209   // Constructors for `Value::Type::STRING`.
210   explicit Value(std::string_view value);
211   explicit Value(std::u16string_view value);
212   // `char*` and `char16_t*` are needed to provide a more specific overload than
213   // the deleted `const T*` overload above.
214   explicit Value(const char* value);
215   explicit Value(const char16_t* value);
216   // `std::string&&` allows for efficient move construction.
217   explicit Value(std::string&& value) noexcept;
218 
219   // Constructors for `Value::Type::BINARY`.
220   explicit Value(const std::vector<char>& value);
221   explicit Value(base::span<const uint8_t> value);
222   explicit Value(BlobStorage&& value) noexcept;
223 
224   // Constructor for `Value::Type::DICT`.
225   explicit Value(Dict&& value) noexcept;
226 
227   // Constructor for `Value::Type::LIST`.
228   explicit Value(List&& value) noexcept;
229 
230   ~Value();
231 
232   // Returns the name for a given `type`.
233   static const char* GetTypeName(Type type);
234 
235   // Returns the type of the value stored by the current Value object.
type()236   Type type() const { return static_cast<Type>(data_.index()); }
237 
238   // Returns true if the current object represents a given type.
is_none()239   bool is_none() const { return type() == Type::NONE; }
is_bool()240   bool is_bool() const { return type() == Type::BOOLEAN; }
is_int()241   bool is_int() const { return type() == Type::INTEGER; }
is_double()242   bool is_double() const { return type() == Type::DOUBLE; }
is_string()243   bool is_string() const { return type() == Type::STRING; }
is_blob()244   bool is_blob() const { return type() == Type::BINARY; }
is_dict()245   bool is_dict() const { return type() == Type::DICT; }
is_list()246   bool is_list() const { return type() == Type::LIST; }
247 
248   // Returns the stored data if the type matches, or `std::nullopt`/`nullptr`
249   // otherwise. `bool`, `int`, and `double` are returned in a wrapped
250   // `std::optional`; blobs, `Value::Dict`, and `Value::List` are returned by
251   // pointer.
252   std::optional<bool> GetIfBool() const;
253   std::optional<int> GetIfInt() const;
254   // Returns a non-null value for both `Value::Type::DOUBLE` and
255   // `Value::Type::INT`, converting the latter to a double.
256   std::optional<double> GetIfDouble() const;
257   const std::string* GetIfString() const;
258   std::string* GetIfString();
259   const BlobStorage* GetIfBlob() const;
260   BlobStorage* GetIfBlob();
261   const Dict* GetIfDict() const;
262   Dict* GetIfDict();
263   const List* GetIfList() const;
264   List* GetIfList();
265 
266   // Similar to the `GetIf...()` variants above, but fails with a `CHECK()` on a
267   // type mismatch. `bool`, `int`, and `double` are returned by value; blobs,
268   // `Value::Dict`, and `Value::List` are returned by reference.
269   bool GetBool() const;
270   int GetInt() const;
271   // Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`,
272   // converting the latter to a double.
273   double GetDouble() const;
274   const std::string& GetString() const LIFETIME_BOUND;
275   std::string& GetString() LIFETIME_BOUND;
276   const BlobStorage& GetBlob() const LIFETIME_BOUND;
277   BlobStorage& GetBlob() LIFETIME_BOUND;
278   const Dict& GetDict() const LIFETIME_BOUND;
279   Dict& GetDict() LIFETIME_BOUND;
280   const List& GetList() const LIFETIME_BOUND;
281   List& GetList() LIFETIME_BOUND;
282 
283   // Transfers ownership of the underlying value. Similarly to `Get...()`
284   // variants above, fails with a `CHECK()` on a type mismatch. After
285   // transferring the ownership `*this` is in a valid, but unspecified, state.
286   // Prefer over `std::move(value.Get...())` so clang-tidy can warn about
287   // potential use-after-move mistakes.
288   std::string TakeString() &&;
289   BlobStorage TakeBlob() &&;
290   Dict TakeDict() &&;
291   List TakeList() &&;
292 
293   // Represents a dictionary of string keys to Values.
294   class BASE_EXPORT GSL_OWNER Dict {
295    public:
296     using iterator = detail::dict_iterator;
297     using const_iterator = detail::const_dict_iterator;
298 
299     Dict();
300 
301     Dict(Dict&&) noexcept;
302     Dict& operator=(Dict&&) noexcept;
303 
304     // Deleted to prevent accidental copying.
305     Dict(const Dict&) = delete;
306     Dict& operator=(const Dict&) = delete;
307 
308     // Takes move_iterators iterators that return std::pair<std::string, Value>,
309     // and moves their values into a new Dict. Adding all entries at once
310     // results in a faster initial sort operation. Takes move iterators to avoid
311     // having to clone the input.
312     template <class IteratorType>
Dict(std::move_iterator<IteratorType> first,std::move_iterator<IteratorType> last)313     explicit Dict(std::move_iterator<IteratorType> first,
314                   std::move_iterator<IteratorType> last) {
315       // Need to move into a vector first, since `storage_` currently uses
316       // unique_ptrs.
317       std::vector<std::pair<std::string, std::unique_ptr<Value>>> values;
318       for (auto current = first; current != last; ++current) {
319         // With move iterators, no need to call Clone(), but do need to move
320         // to a temporary first, as accessing either field individually will
321         // directly from the iterator will delete the other field.
322         auto value = *current;
323         values.emplace_back(std::move(value.first),
324                             std::make_unique<Value>(std::move(value.second)));
325       }
326       storage_ =
327           flat_map<std::string, std::unique_ptr<Value>>(std::move(values));
328     }
329 
330     ~Dict();
331 
332     // Returns true if there are no entries in this dictionary and false
333     // otherwise.
334     bool empty() const;
335 
336     // Returns the number of entries in this dictionary.
337     size_t size() const;
338 
339     // Returns an iterator to the first entry in this dictionary.
340     iterator begin();
341     const_iterator begin() const;
342     const_iterator cbegin() const;
343 
344     // Returns an iterator following the last entry in this dictionary. May not
345     // be dereferenced.
346     iterator end();
347     const_iterator end() const;
348     const_iterator cend() const;
349 
350     // Returns true if `key` is an entry in this dictionary.
351     bool contains(std::string_view key) const;
352 
353     // Removes all entries from this dictionary.
354     REINITIALIZES_AFTER_MOVE void clear();
355 
356     // Removes the entry referenced by `pos` in this dictionary and returns an
357     // iterator to the entry following the removed entry.
358     iterator erase(iterator pos);
359     iterator erase(const_iterator pos);
360 
361     // Creates a deep copy of this dictionary.
362     Dict Clone() const;
363 
364     // Merges the entries from `dict` into this dictionary. If an entry with the
365     // same key exists in this dictionary and `dict`:
366     // - if both entries are dictionaries, they will be recursively merged
367     // - otherwise, the already-existing entry in this dictionary will be
368     //   overwritten with the entry from `dict`.
369     void Merge(Dict dict);
370 
371     // Finds the entry corresponding to `key` in this dictionary. Returns
372     // nullptr if there is no such entry.
373     const Value* Find(std::string_view key) const;
374     Value* Find(std::string_view key);
375 
376     // Similar to `Find()` above, but returns `std::nullopt`/`nullptr` if the
377     // type of the entry does not match. `bool`, `int`, and `double` are
378     // returned in a wrapped `std::optional`; blobs, `Value::Dict`, and
379     // `Value::List` are returned by pointer.
380     std::optional<bool> FindBool(std::string_view key) const;
381     std::optional<int> FindInt(std::string_view key) const;
382     // Returns a non-null value for both `Value::Type::DOUBLE` and
383     // `Value::Type::INT`, converting the latter to a double.
384     std::optional<double> FindDouble(std::string_view key) const;
385     const std::string* FindString(std::string_view key) const;
386     std::string* FindString(std::string_view key);
387     const BlobStorage* FindBlob(std::string_view key) const;
388     BlobStorage* FindBlob(std::string_view key);
389     const Dict* FindDict(std::string_view key) const;
390     Dict* FindDict(std::string_view key);
391     const List* FindList(std::string_view key) const;
392     List* FindList(std::string_view key);
393 
394     // If there's a value of the specified type at `key` in this dictionary,
395     // returns it. Otherwise, creates an empty container of the specified type,
396     // inserts it at `key`, and returns it. If there's a value of some other
397     // type at `key`, will overwrite that entry.
398     Dict* EnsureDict(std::string_view key);
399     List* EnsureList(std::string_view key);
400 
401     // Sets an entry with `key` and `value` in this dictionary, overwriting any
402     // existing entry with the same `key`. Returns a pointer to the set `value`.
403     Value* Set(std::string_view key, Value&& value) &;
404     Value* Set(std::string_view key, bool value) &;
405     template <typename T>
406     Value* Set(std::string_view, const T*) & = delete;
407     Value* Set(std::string_view key, int value) &;
408     Value* Set(std::string_view key, double value) &;
409     Value* Set(std::string_view key, std::string_view value) &;
410     Value* Set(std::string_view key, std::u16string_view value) &;
411     Value* Set(std::string_view key, const char* value) &;
412     Value* Set(std::string_view key, const char16_t* value) &;
413     Value* Set(std::string_view key, std::string&& value) &;
414     Value* Set(std::string_view key, BlobStorage&& value) &;
415     Value* Set(std::string_view key, Dict&& value) &;
416     Value* Set(std::string_view key, List&& value) &;
417 
418     // Rvalue overrides of the `Set` methods, which allow you to construct
419     // a `Value::Dict` builder-style:
420     //
421     // Value::Dict result =
422     //     Value::Dict()
423     //         .Set("key-1", "first value")
424     //         .Set("key-2", 2)
425     //         .Set("key-3", true)
426     //         .Set("nested-dictionary", Value::Dict()
427     //                                       .Set("nested-key-1", "value")
428     //                                       .Set("nested-key-2", true))
429     //         .Set("nested-list", Value::List()
430     //                                 .Append("nested-list-value")
431     //                                 .Append(5)
432     //                                 .Append(true));
433     //
434     // Each method returns a rvalue reference to `this`, so this is as efficient
435     // as stand-alone calls to `Set`, while also making it harder to
436     // accidentally insert items in the wrong dictionary.
437     //
438     // The equivalent code without using these builder-style methods:
439     //
440     // Value::Dict no_builder_example;
441     // no_builder_example.Set("key-1", "first value")
442     // no_builder_example.Set("key-2", 2)
443     // no_builder_example.Set("key-3", true)
444     // Value::Dict nested_dictionary;
445     // nested_dictionary.Set("nested-key-1", "value");
446     // nested_dictionary.Set("nested-key-2", true);
447     // no_builder_example.Set("nested_dictionary",
448     //                        std::move(nested_dictionary));
449     // Value::List nested_list;
450     // nested_list.Append("nested-list-value");
451     // nested_list.Append(5);
452     // nested_list.Append(true);
453     // no_builder_example.Set("nested-list", std::move(nested_list));
454     //
455     // Sometimes `git cl format` does a less than perfect job formatting these
456     // chained `Set` calls. In these cases you can use a trailing empty comment
457     // to influence the code formatting:
458     //
459     // Value::Dict result = Value::Dict().Set(
460     //     "nested",
461     //     base::Value::Dict().Set("key", "value").Set("other key", "other"));
462     //
463     // Value::Dict result = Value::Dict().Set("nested",
464     //                                        base::Value::Dict() //
465     //                                           .Set("key", "value")
466     //                                           .Set("other key", "value"));
467     //
468     Dict&& Set(std::string_view key, Value&& value) &&;
469     Dict&& Set(std::string_view key, bool value) &&;
470     template <typename T>
471     Dict&& Set(std::string_view, const T*) && = delete;
472     Dict&& Set(std::string_view key, int value) &&;
473     Dict&& Set(std::string_view key, double value) &&;
474     Dict&& Set(std::string_view key, std::string_view value) &&;
475     Dict&& Set(std::string_view key, std::u16string_view value) &&;
476     Dict&& Set(std::string_view key, const char* value) &&;
477     Dict&& Set(std::string_view key, const char16_t* value) &&;
478     Dict&& Set(std::string_view key, std::string&& value) &&;
479     Dict&& Set(std::string_view key, BlobStorage&& value) &&;
480     Dict&& Set(std::string_view key, Dict&& value) &&;
481     Dict&& Set(std::string_view key, List&& value) &&;
482 
483     // Removes the entry corresponding to `key` from this dictionary. Returns
484     // true if an entry was removed or false otherwise.
485     bool Remove(std::string_view key);
486 
487     // Similar to `Remove()`, but returns the value corresponding to the removed
488     // entry or `std::nullopt` otherwise.
489     std::optional<Value> Extract(std::string_view key);
490 
491     // Equivalent to the above methods but operating on paths instead of keys.
492     // A path is shorthand syntax for referring to a key nested inside
493     // intermediate dictionaries, with components delimited by ".". Paths may
494     // not be empty.
495     //
496     // Prefer the non-path methods above when possible. Paths that have only one
497     // component (i.e. no dots in the path) should never use the path-based
498     // methods.
499     //
500     // Originally, the path-based APIs were the only way of specifying a key, so
501     // there are likely to be many legacy (and unnecessary) uses of the path
502     // APIs that do not actually require traversing nested dictionaries.
503     const Value* FindByDottedPath(std::string_view path) const;
504     Value* FindByDottedPath(std::string_view path);
505 
506     std::optional<bool> FindBoolByDottedPath(std::string_view path) const;
507     std::optional<int> FindIntByDottedPath(std::string_view path) const;
508     // Returns a non-null value for both `Value::Type::DOUBLE` and
509     // `Value::Type::INT`, converting the latter to a double.
510     std::optional<double> FindDoubleByDottedPath(std::string_view path) const;
511     const std::string* FindStringByDottedPath(std::string_view path) const;
512     std::string* FindStringByDottedPath(std::string_view path);
513     const BlobStorage* FindBlobByDottedPath(std::string_view path) const;
514     BlobStorage* FindBlobByDottedPath(std::string_view path);
515     const Dict* FindDictByDottedPath(std::string_view path) const;
516     Dict* FindDictByDottedPath(std::string_view path);
517     const List* FindListByDottedPath(std::string_view path) const;
518     List* FindListByDottedPath(std::string_view path);
519 
520     // Creates a new entry with a dictionary for any non-last component that is
521     // missing an entry while performing the path traversal. Will fail if any
522     // non-last component of the path refers to an already-existing entry that
523     // is not a dictionary. Returns `nullptr` on failure.
524     //
525     // Warning: repeatedly using this API to enter entries in the same nested
526     // dictionary is inefficient, so please do not write the following:
527     //
528     // bad_example.SetByDottedPath("a.nested.dictionary.field_1", 1);
529     // bad_example.SetByDottedPath("a.nested.dictionary.field_2", "value");
530     // bad_example.SetByDottedPath("a.nested.dictionary.field_3", 1);
531     //
532     Value* SetByDottedPath(std::string_view path, Value&& value) &;
533     Value* SetByDottedPath(std::string_view path, bool value) &;
534     template <typename T>
535     Value* SetByDottedPath(std::string_view, const T*) & = delete;
536     Value* SetByDottedPath(std::string_view path, int value) &;
537     Value* SetByDottedPath(std::string_view path, double value) &;
538     Value* SetByDottedPath(std::string_view path, std::string_view value) &;
539     Value* SetByDottedPath(std::string_view path, std::u16string_view value) &;
540     Value* SetByDottedPath(std::string_view path, const char* value) &;
541     Value* SetByDottedPath(std::string_view path, const char16_t* value) &;
542     Value* SetByDottedPath(std::string_view path, std::string&& value) &;
543     Value* SetByDottedPath(std::string_view path, BlobStorage&& value) &;
544     Value* SetByDottedPath(std::string_view path, Dict&& value) &;
545     Value* SetByDottedPath(std::string_view path, List&& value) &;
546 
547     // Rvalue overrides of the `SetByDottedPath` methods, which allow you to
548     // construct a `Value::Dict` builder-style:
549     //
550     // Value::Dict result =
551     //     Value::Dict()
552     //         .SetByDottedPath("a.nested.dictionary.with.key-1", "first value")
553     //         .Set("local-key-1", 2));
554     //
555     // Each method returns a rvalue reference to `this`, so this is as efficient
556     // as (and less mistake-prone than) stand-alone calls to `Set`.
557     //
558     // Warning: repeatedly using this API to enter entries in the same nested
559     // dictionary is inefficient, so do not write this:
560     //
561     // Value::Dict bad_example =
562     //   Value::Dict()
563     //     .SetByDottedPath("nested.dictionary.key-1", "first value")
564     //     .SetByDottedPath("nested.dictionary.key-2", "second value")
565     //     .SetByDottedPath("nested.dictionary.key-3", "third value");
566     //
567     // Instead, simply write this
568     //
569     // Value::Dict good_example =
570     //   Value::Dict()
571     //     .Set("nested",
572     //          base::Value::Dict()
573     //            .Set("dictionary",
574     //                 base::Value::Dict()
575     //                   .Set(key-1", "first value")
576     //                   .Set(key-2", "second value")
577     //                   .Set(key-3", "third value")));
578     //
579     //
580     Dict&& SetByDottedPath(std::string_view path, Value&& value) &&;
581     Dict&& SetByDottedPath(std::string_view path, bool value) &&;
582     template <typename T>
583     Dict&& SetByDottedPath(std::string_view, const T*) && = delete;
584     Dict&& SetByDottedPath(std::string_view path, int value) &&;
585     Dict&& SetByDottedPath(std::string_view path, double value) &&;
586     Dict&& SetByDottedPath(std::string_view path, std::string_view value) &&;
587     Dict&& SetByDottedPath(std::string_view path, std::u16string_view value) &&;
588     Dict&& SetByDottedPath(std::string_view path, const char* value) &&;
589     Dict&& SetByDottedPath(std::string_view path, const char16_t* value) &&;
590     Dict&& SetByDottedPath(std::string_view path, std::string&& value) &&;
591     Dict&& SetByDottedPath(std::string_view path, BlobStorage&& value) &&;
592     Dict&& SetByDottedPath(std::string_view path, Dict&& value) &&;
593     Dict&& SetByDottedPath(std::string_view path, List&& value) &&;
594 
595     bool RemoveByDottedPath(std::string_view path);
596 
597     std::optional<Value> ExtractByDottedPath(std::string_view path);
598 
599     // Estimates dynamic memory usage. Requires tracing support
600     // (enable_base_tracing gn flag), otherwise always returns 0. See
601     // base/trace_event/memory_usage_estimator.h for more info.
602     size_t EstimateMemoryUsage() const;
603 
604     // Serializes to a string for logging and debug purposes.
605     std::string DebugString() const;
606 
607 #if BUILDFLAG(ENABLE_BASE_TRACING)
608     // Write this object into a trace.
609     void WriteIntoTrace(perfetto::TracedValue) const;
610 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
611 
612    private:
613     BASE_EXPORT friend bool operator==(const Dict& lhs, const Dict& rhs);
614     BASE_EXPORT friend bool operator!=(const Dict& lhs, const Dict& rhs);
615     BASE_EXPORT friend bool operator<(const Dict& lhs, const Dict& rhs);
616     BASE_EXPORT friend bool operator>(const Dict& lhs, const Dict& rhs);
617     BASE_EXPORT friend bool operator<=(const Dict& lhs, const Dict& rhs);
618     BASE_EXPORT friend bool operator>=(const Dict& lhs, const Dict& rhs);
619 
620     // TODO(dcheng): Replace with `flat_map<std::string, Value>` once no caller
621     // relies on stability of pointers anymore.
622     flat_map<std::string, std::unique_ptr<Value>> storage_;
623   };
624 
625   // Represents a list of Values.
626   class BASE_EXPORT GSL_OWNER List {
627    public:
628     using iterator = CheckedContiguousIterator<Value>;
629     using const_iterator = CheckedContiguousConstIterator<Value>;
630     using reverse_iterator = std::reverse_iterator<iterator>;
631     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
632     using value_type = Value;
633 
634     // Creates a list with the given capacity reserved.
635     // Correctly using this will greatly reduce the code size and improve
636     // performance when creating a list whose size is known up front.
637     static List with_capacity(size_t capacity);
638 
639     List();
640 
641     List(List&&) noexcept;
642     List& operator=(List&&) noexcept;
643 
644     // Deleted to prevent accidental copying.
645     List(const List&) = delete;
646     List& operator=(const List&) = delete;
647 
648     ~List();
649 
650     // Returns true if there are no values in this list and false otherwise.
651     bool empty() const;
652 
653     // Returns the number of values in this list.
654     size_t size() const;
655 
656     // Returns an iterator to the first value in this list.
657     iterator begin();
658     const_iterator begin() const;
659     const_iterator cbegin() const;
660 
661     // Returns an iterator following the last value in this list. May not be
662     // dereferenced.
663     iterator end();
664     const_iterator end() const;
665     const_iterator cend() const;
666 
667     // Returns a reverse iterator preceding the first value in this list. May
668     // not be dereferenced.
669     reverse_iterator rend();
670     const_reverse_iterator rend() const;
671 
672     // Returns a reverse iterator to the last value in this list.
673     reverse_iterator rbegin();
674     const_reverse_iterator rbegin() const;
675 
676     // Returns a reference to the first value in the container. Fails with
677     // `CHECK()` if the list is empty.
678     const Value& front() const LIFETIME_BOUND;
679     Value& front() LIFETIME_BOUND;
680 
681     // Returns a reference to the last value in the container. Fails with
682     // `CHECK()` if the list is empty.
683     const Value& back() const LIFETIME_BOUND;
684     Value& back() LIFETIME_BOUND;
685 
686     // Increase the capacity of the backing container, but does not change
687     // the size. Assume all existing iterators will be invalidated.
688     void reserve(size_t capacity);
689 
690     // Resizes the list.
691     // If `new_size` is greater than current size, the extra elements in the
692     // back will be destroyed.
693     // If `new_size` is less than current size, new default-initialized elements
694     // will be added to the back.
695     // Assume all existing iterators will be invalidated.
696     void resize(size_t new_size);
697 
698     // Returns a reference to the value at `index` in this list. Fails with a
699     // `CHECK()` if `index >= size()`.
700     const Value& operator[](size_t index) const;
701     Value& operator[](size_t index);
702 
703     // Removes all value from this list.
704     REINITIALIZES_AFTER_MOVE void clear();
705 
706     // Removes the value referenced by `pos` in this list and returns an
707     // iterator to the value following the removed value.
708     iterator erase(iterator pos);
709     const_iterator erase(const_iterator pos);
710 
711     // Remove the values in the range [`first`, `last`). Returns iterator to the
712     // first value following the removed range, which is `last`. If `first` ==
713     // `last`, removes nothing and returns `last`.
714     iterator erase(iterator first, iterator last);
715     const_iterator erase(const_iterator first, const_iterator last);
716 
717     // Creates a deep copy of this dictionary.
718     List Clone() const;
719 
720     // Appends `value` to the end of this list.
721     void Append(Value&& value) &;
722     void Append(bool value) &;
723     template <typename T>
724     void Append(const T*) & = delete;
725     void Append(int value) &;
726     void Append(double value) &;
727     void Append(std::string_view value) &;
728     void Append(std::u16string_view value) &;
729     void Append(const char* value) &;
730     void Append(const char16_t* value) &;
731     void Append(std::string&& value) &;
732     void Append(BlobStorage&& value) &;
733     void Append(Dict&& value) &;
734     void Append(List&& value) &;
735 
736     // Rvalue overrides of the `Append` methods, which allow you to construct
737     // a `Value::List` builder-style:
738     //
739     // Value::List result =
740     //   Value::List().Append("first value").Append(2).Append(true);
741     //
742     // Each method returns a rvalue reference to `this`, so this is as efficient
743     // as stand-alone calls to `Append`, while at the same time making it harder
744     // to accidentally append to the wrong list.
745     //
746     // The equivalent code without using these builder-style methods:
747     //
748     // Value::List no_builder_example;
749     // no_builder_example.Append("first value");
750     // no_builder_example.Append(2);
751     // no_builder_example.Append(true);
752     //
753     List&& Append(Value&& value) &&;
754     List&& Append(bool value) &&;
755     template <typename T>
756     List&& Append(const T*) && = delete;
757     List&& Append(int value) &&;
758     List&& Append(double value) &&;
759     List&& Append(std::string_view value) &&;
760     List&& Append(std::u16string_view value) &&;
761     List&& Append(const char* value) &&;
762     List&& Append(const char16_t* value) &&;
763     List&& Append(std::string&& value) &&;
764     List&& Append(BlobStorage&& value) &&;
765     List&& Append(Dict&& value) &&;
766     List&& Append(List&& value) &&;
767 
768     // Inserts `value` before `pos` in this list. Returns an iterator to the
769     // inserted value.
770     // TODO(dcheng): Should this provide the same set of overloads that Append()
771     // does?
772     iterator Insert(const_iterator pos, Value&& value);
773 
774     // Erases all values equal to `value` from this list.
775     size_t EraseValue(const Value& value);
776 
777     // Erases all values for which `predicate` evaluates to true from this list.
778     template <typename Predicate>
EraseIf(Predicate predicate)779     size_t EraseIf(Predicate predicate) {
780       return std::erase_if(storage_, predicate);
781     }
782 
783     // Estimates dynamic memory usage. Requires tracing support
784     // (enable_base_tracing gn flag), otherwise always returns 0. See
785     // base/trace_event/memory_usage_estimator.h for more info.
786     size_t EstimateMemoryUsage() const;
787 
788     // Serializes to a string for logging and debug purposes.
789     std::string DebugString() const;
790 
791 #if BUILDFLAG(ENABLE_BASE_TRACING)
792     // Write this object into a trace.
793     void WriteIntoTrace(perfetto::TracedValue) const;
794 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
795 
796    private:
797     using ListStorage = std::vector<Value>;
798 
799     BASE_EXPORT friend bool operator==(const List& lhs, const List& rhs);
800     BASE_EXPORT friend bool operator!=(const List& lhs, const List& rhs);
801     BASE_EXPORT friend bool operator<(const List& lhs, const List& rhs);
802     BASE_EXPORT friend bool operator>(const List& lhs, const List& rhs);
803     BASE_EXPORT friend bool operator<=(const List& lhs, const List& rhs);
804     BASE_EXPORT friend bool operator>=(const List& lhs, const List& rhs);
805 
806     explicit List(const std::vector<Value>& storage);
807 
808     std::vector<Value> storage_;
809   };
810 
811   // Note: Do not add more types. See the file-level comment above for why.
812 
813   // Comparison operators so that Values can easily be used with standard
814   // library algorithms and associative containers.
815   BASE_EXPORT friend bool operator==(const Value& lhs, const Value& rhs);
816   BASE_EXPORT friend bool operator!=(const Value& lhs, const Value& rhs);
817   BASE_EXPORT friend bool operator<(const Value& lhs, const Value& rhs);
818   BASE_EXPORT friend bool operator>(const Value& lhs, const Value& rhs);
819   BASE_EXPORT friend bool operator<=(const Value& lhs, const Value& rhs);
820   BASE_EXPORT friend bool operator>=(const Value& lhs, const Value& rhs);
821 
822   BASE_EXPORT friend bool operator==(const Value& lhs, bool rhs);
823   friend bool operator==(bool lhs, const Value& rhs) { return rhs == lhs; }
824   friend bool operator!=(const Value& lhs, bool rhs) { return !(lhs == rhs); }
825   friend bool operator!=(bool lhs, const Value& rhs) { return !(lhs == rhs); }
826   template <typename T>
827   friend bool operator==(const Value& lhs, const T* rhs) = delete;
828   template <typename T>
829   friend bool operator==(const T* lhs, const Value& rhs) = delete;
830   template <typename T>
831   friend bool operator!=(const Value& lhs, const T* rhs) = delete;
832   template <typename T>
833   friend bool operator!=(const T* lhs, const Value& rhs) = delete;
834   BASE_EXPORT friend bool operator==(const Value& lhs, int rhs);
835   friend bool operator==(int lhs, const Value& rhs) { return rhs == lhs; }
836   friend bool operator!=(const Value& lhs, int rhs) { return !(lhs == rhs); }
837   friend bool operator!=(int lhs, const Value& rhs) { return !(lhs == rhs); }
838   BASE_EXPORT friend bool operator==(const Value& lhs, double rhs);
839   friend bool operator==(double lhs, const Value& rhs) { return rhs == lhs; }
840   friend bool operator!=(const Value& lhs, double rhs) { return !(lhs == rhs); }
841   friend bool operator!=(double lhs, const Value& rhs) { return !(lhs == rhs); }
842   // Note: std::u16string_view overload intentionally omitted: Value internally
843   // stores strings as UTF-8. While it is possible to implement a comparison
844   // operator that would not require first creating a new UTF-8 string from the
845   // UTF-16 string argument, it is simpler to just not implement it at all for a
846   // rare use case.
847   BASE_EXPORT friend bool operator==(const Value& lhs, std::string_view rhs);
848   friend bool operator==(std::string_view lhs, const Value& rhs) {
849     return rhs == lhs;
850   }
851   friend bool operator!=(const Value& lhs, std::string_view rhs) {
852     return !(lhs == rhs);
853   }
854   friend bool operator!=(std::string_view lhs, const Value& rhs) {
855     return !(lhs == rhs);
856   }
857   friend bool operator==(const Value& lhs, const char* rhs) {
858     return lhs == std::string_view(rhs);
859   }
860   friend bool operator==(const char* lhs, const Value& rhs) {
861     return rhs == lhs;
862   }
863   friend bool operator!=(const Value& lhs, const char* rhs) {
864     return !(lhs == rhs);
865   }
866   friend bool operator!=(const char* lhs, const Value& rhs) {
867     return !(lhs == rhs);
868   }
869   friend bool operator==(const Value& lhs, const std::string& rhs) {
870     return lhs == std::string_view(rhs);
871   }
872   friend bool operator==(const std::string& lhs, const Value& rhs) {
873     return rhs == lhs;
874   }
875   friend bool operator!=(const Value& lhs, const std::string& rhs) {
876     return !(lhs == rhs);
877   }
878   friend bool operator!=(const std::string& lhs, const Value& rhs) {
879     return !(lhs == rhs);
880   }
881   // Note: Blob support intentionally omitted as an experiment for potentially
882   // wholly removing Blob support from Value itself in the future.
883   BASE_EXPORT friend bool operator==(const Value& lhs, const Value::Dict& rhs);
884   friend bool operator==(const Value::Dict& lhs, const Value& rhs) {
885     return rhs == lhs;
886   }
887   friend bool operator!=(const Value& lhs, const Value::Dict& rhs) {
888     return !(lhs == rhs);
889   }
890   friend bool operator!=(const Value::Dict& lhs, const Value& rhs) {
891     return !(lhs == rhs);
892   }
893   BASE_EXPORT friend bool operator==(const Value& lhs, const Value::List& rhs);
894   friend bool operator==(const Value::List& lhs, const Value& rhs) {
895     return rhs == lhs;
896   }
897   friend bool operator!=(const Value& lhs, const Value::List& rhs) {
898     return !(lhs == rhs);
899   }
900   friend bool operator!=(const Value::List& lhs, const Value& rhs) {
901     return !(lhs == rhs);
902   }
903 
904   // Estimates dynamic memory usage. Requires tracing support
905   // (enable_base_tracing gn flag), otherwise always returns 0. See
906   // base/trace_event/memory_usage_estimator.h for more info.
907   size_t EstimateMemoryUsage() const;
908 
909   // Serializes to a string for logging and debug purposes.
910   std::string DebugString() const;
911 
912 #if BUILDFLAG(ENABLE_BASE_TRACING)
913   // Write this object into a trace.
914   void WriteIntoTrace(perfetto::TracedValue) const;
915 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
916 
917   template <typename Visitor>
Visit(Visitor && visitor)918   auto Visit(Visitor&& visitor) const {
919     return absl::visit(std::forward<Visitor>(visitor), data_);
920   }
921 
922  private:
923   // For access to DoubleStorage.
924   friend class ValueView;
925 
926   // Special case for doubles, which are aligned to 8 bytes on some
927   // 32-bit architectures. In this case, a simple declaration as a
928   // double member would make the whole union 8 byte-aligned, which
929   // would also force 4 bytes of wasted padding space before it in
930   // the Value layout.
931   //
932   // To override this, store the value as an array of 32-bit integers, and
933   // perform the appropriate bit casts when reading / writing to it.
934   class BASE_EXPORT DoubleStorage {
935    public:
936     explicit DoubleStorage(double v);
937     DoubleStorage(const DoubleStorage&) = default;
938     DoubleStorage& operator=(const DoubleStorage&) = default;
939 
940     // Provide an implicit conversion to double to simplify the use of visitors
941     // with `Value::Visit()`. Otherwise, visitors would need a branch for
942     // handling `DoubleStorage` like:
943     //
944     //   value.Visit([] (const auto& member) {
945     //     using T = std::decay_t<decltype(member)>;
946     //     if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
947     //       SomeFunction(double{member});
948     //     } else {
949     //       SomeFunction(member);
950     //     }
951     //   });
952     operator double() const { return base::bit_cast<double>(v_); }
953 
954    private:
955     friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
956       return double{lhs} == double{rhs};
957     }
958 
959     friend bool operator!=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
960       return !(lhs == rhs);
961     }
962 
963     friend bool operator<(const DoubleStorage& lhs, const DoubleStorage& rhs) {
964       return double{lhs} < double{rhs};
965     }
966 
967     friend bool operator>(const DoubleStorage& lhs, const DoubleStorage& rhs) {
968       return rhs < lhs;
969     }
970 
971     friend bool operator<=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
972       return !(rhs < lhs);
973     }
974 
975     friend bool operator>=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
976       return !(lhs < rhs);
977     }
978 
979     alignas(4) std::array<char, sizeof(double)> v_;
980   };
981 
982   // Internal constructors, allowing the simplify the implementation of Clone().
983   explicit Value(absl::monostate);
984   explicit Value(DoubleStorage storage);
985 
986   // A helper for static functions used for cloning a Value or a ValueView.
987   class CloningHelper;
988 
989   absl::variant<absl::monostate,
990                 bool,
991                 int,
992                 DoubleStorage,
993                 std::string,
994                 BlobStorage,
995                 Dict,
996                 List>
997       data_;
998 };
999 
1000 // Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON
1001 // serialization methods without having to clone the contents and transfer
1002 // ownership of the clone to a `Value` wrapper object.
1003 //
1004 // Like `std::string_view` and `span<T>`, this adapter does NOT retain
1005 // ownership. Any underlying object that is passed by reference (i.e.
1006 // `std::string`, `Value::BlobStorage`, `Value::Dict`, `Value::List`, or
1007 // `Value`) MUST remain live as long as there is a `ValueView` referencing it.
1008 //
1009 // While it might be nice to just use the `absl::variant` type directly, the
1010 // need to use `std::reference_wrapper` makes it clunky. `absl::variant` and
1011 // `std::reference_wrapper` both support implicit construction, but C++ only
1012 // allows at most one user-defined conversion in an implicit conversion
1013 // sequence. If this adapter and its implicit constructors did not exist,
1014 // callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or
1015 // `Value::List` to a function with a `ValueView` parameter.
1016 class BASE_EXPORT GSL_POINTER ValueView {
1017  public:
1018   ValueView() = default;
ValueView(bool value)1019   ValueView(bool value) : data_view_(value) {}
1020   template <typename T>
1021   ValueView(const T*) = delete;
ValueView(int value)1022   ValueView(int value) : data_view_(value) {}
ValueView(double value)1023   ValueView(double value)
1024       : data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {}
ValueView(std::string_view value)1025   ValueView(std::string_view value) : data_view_(value) {}
ValueView(const char * value)1026   ValueView(const char* value) : ValueView(std::string_view(value)) {}
ValueView(const std::string & value)1027   ValueView(const std::string& value) : ValueView(std::string_view(value)) {}
1028   // Note: UTF-16 is intentionally not supported. ValueView is intended to be a
1029   // low-cost view abstraction, but Value internally represents strings as
1030   // UTF-8, so it would not be possible to implement this without allocating an
1031   // entirely new UTF-8 string.
ValueView(const Value::BlobStorage & value)1032   ValueView(const Value::BlobStorage& value) : data_view_(value) {}
ValueView(const Value::Dict & value)1033   ValueView(const Value::Dict& value) : data_view_(value) {}
ValueView(const Value::List & value)1034   ValueView(const Value::List& value) : data_view_(value) {}
1035   ValueView(const Value& value);
1036 
1037   // This is the only 'getter' method provided as `ValueView` is not intended
1038   // to be a general replacement of `Value`.
1039   template <typename Visitor>
Visit(Visitor && visitor)1040   auto Visit(Visitor&& visitor) const {
1041     return absl::visit(std::forward<Visitor>(visitor), data_view_);
1042   }
1043 
1044   // Returns a clone of the underlying Value.
1045   Value ToValue() const;
1046 
1047  private:
1048   using ViewType =
1049       absl::variant<absl::monostate,
1050                     bool,
1051                     int,
1052                     Value::DoubleStorage,
1053                     std::string_view,
1054                     std::reference_wrapper<const Value::BlobStorage>,
1055                     std::reference_wrapper<const Value::Dict>,
1056                     std::reference_wrapper<const Value::List>>;
1057 
1058  public:
1059   using DoubleStorageForTest = Value::DoubleStorage;
data_view_for_test()1060   const ViewType& data_view_for_test() const { return data_view_; }
1061 
1062  private:
1063   ViewType data_view_;
1064 };
1065 
1066 // This interface is implemented by classes that know how to serialize
1067 // Value objects.
1068 class BASE_EXPORT ValueSerializer {
1069  public:
1070   virtual ~ValueSerializer();
1071 
1072   virtual bool Serialize(ValueView root) = 0;
1073 };
1074 
1075 // This interface is implemented by classes that know how to deserialize Value
1076 // objects.
1077 class BASE_EXPORT ValueDeserializer {
1078  public:
1079   virtual ~ValueDeserializer();
1080 
1081   // This method deserializes the subclass-specific format into a Value object.
1082   // If the return value is non-NULL, the caller takes ownership of returned
1083   // Value.
1084   //
1085   // If the return value is nullptr, and if `error_code` is non-nullptr,
1086   // `*error_code` will be set to an integer value representing the underlying
1087   // error. See "enum ErrorCode" below for more detail about the integer value.
1088   //
1089   // If `error_message` is non-nullptr, it will be filled in with a formatted
1090   // error message including the location of the error if appropriate.
1091   virtual std::unique_ptr<Value> Deserialize(int* error_code,
1092                                              std::string* error_message) = 0;
1093 
1094   // The integer-valued error codes form four groups:
1095   //  - The value 0 means no error.
1096   //  - Values between 1 and 999 inclusive mean an error in the data (i.e.
1097   //    content). The bytes being deserialized are not in the right format.
1098   //  - Values 1000 and above mean an error in the metadata (i.e. context). The
1099   //    file could not be read, the network is down, etc.
1100   //  - Negative values are reserved.
1101   //
1102   // These values are persisted to logs. Entries should not be renumbered and
1103   // numeric values should never be reused.
1104   enum ErrorCode {
1105     kErrorCodeNoError = 0,
1106     // kErrorCodeInvalidFormat is a generic error code for "the data is not in
1107     // the right format". Subclasses of ValueDeserializer may return other
1108     // values for more specific errors.
1109     kErrorCodeInvalidFormat = 1,
1110     // kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
1111     // range of metadata errors.
1112     kErrorCodeFirstMetadataError = 1000,
1113   };
1114 
1115   // The `error_code` argument can be one of the ErrorCode values, but it is
1116   // not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
1117   // can define their own error code values.
ErrorCodeIsDataError(int error_code)1118   static inline bool ErrorCodeIsDataError(int error_code) {
1119     return (kErrorCodeInvalidFormat <= error_code) &&
1120            (error_code < kErrorCodeFirstMetadataError);
1121   }
1122 };
1123 
1124 // Stream operator so Values can be pretty printed by gtest.
1125 BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value);
1126 BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1127                                      const Value::Dict& dict);
1128 BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1129                                      const Value::List& list);
1130 
1131 // Stream operator so that enum class Types can be used in log statements.
1132 BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1133                                      const Value::Type& type);
1134 
1135 }  // namespace base
1136 
1137 #endif  // BASE_VALUES_H_
1138