File: pickle.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (180 lines) | stat: -rw-r--r-- 6,691 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Extensible serialization and deserialization functions for base::Pickle.
//
// This file provides a way to serialize and deserialize arbitrary types to and
// from a base::Pickle. The PickleTraits<T> class template is used to define
// serialization and deserialization for a type T.
//
// By default, all built-in integer types, bools, almost all std::, absl:: and
// base:: container types are supported, along with std::optional, tuple and
// pair types. Supported types may be nested to arbitrary depth, for example
// std::map<std::string, std::vector<int>>.
//
// To serialize a value of type T, call:
//
//   base::Pickle pickle;
//   net::WriteToPickle(pickle, value);
//
// To deserialize a value of type T, call:
//
//   auto pickle = base::Pickle::WithData(data);
//   std::optional<T> value = net::ReadValueFromPickle<T>(iter);
//
// When deserialization fails, the return value will be std::nullopt.
//
// Alternatively, when deserializing a class object, it may be more convenient
// to use ReadPickleInto(), eg.
//
//   auto pickle = base::Pickle::WithData(data);
//   if (!net::ReadPickleInto(pickle, instance.member1_, instance.member2_)) {
//     return std::nullopt;
//   }
//   return instance;
//
// See pickle_traits.h for how to define serialization and deserialization for
// your own types.
//
// Limitations:
//  - Trying to serialize a container with more than INT_MAX elements will
//    result in a CHECK failure. base::Pickle is probably not the right tool for
//    the job if you need to serialize more than 2G elements.
//  - Serializing size_t will give incompatible results on 32-bit and 64-bit
//    platforms. This is one reason why containers are serialized with a 32-bit
//    value for the length.
//
// Intentionally unsupported:
//  - pointer types
//
// Not currently supported:
//  - float, double, long double
//  - std::forward_list
//  - std::array
//  - std::variant
//  - enums

#ifndef NET_BASE_PICKLE_H_
#define NET_BASE_PICKLE_H_

#include <optional>
#include <tuple>

#include "base/pickle.h"
#include "net/base/pickle_traits.h"

namespace net {

// Serializes `args` to `pickle`.
template <typename... Args>
  requires(internal::CanSerialize<Args> && ...)
void WriteToPickle(base::Pickle& pickle, const Args&... args) {
  static_assert((!std::is_const_v<Args> && ...));
  pickle.Reserve(EstimatePickleSize(args...));
  // "," is used in place of ";" here so that we can use template pack
  // expansion.
  (PickleTraits<Args>::Serialize(pickle, args), ...);
}

// Deserializes a single value of type T from `iter`. Returns std::nullopt on
// failure.
template <typename T>
  requires(internal::CanDeserialize<T>)
std::optional<T> ReadValueFromPickle(base::PickleIterator& iter) {
  // Always remove const qualifier before attempting to deserialize.
  // Deserialization always creates a new value, and some deserializers will
  // choke on value they can't write to.
  return PickleTraits<std::remove_const_t<T>>::Deserialize(iter);
}

// Deserializes multiple values from `iter` and returns them as an optional
// tuple. Example usage:
//
//   auto pickle = base::Pickle::WithData(data);
//   auto maybe_value =
//       net::ReadValuesFromPickle<int, std::string>(iter);
//   if (!maybe_value) {
//     return std::nullopt;
//   }
//   auto [int_param, string_param] = std::move(maybe_value).value();
//   return MyType(int_param, string_param);
//
// Returns std::nullopt on failure.
template <typename... Args>
  requires(internal::CanDeserialize<Args> && ...)
std::optional<std::tuple<Args...>> ReadValuesFromPickle(
    base::PickleIterator& iter) {
  return ReadValueFromPickle<std::tuple<Args...>>(iter);
}

// Deserializes multiple values from `iter` and stores them in `args`. Returns
// false and doesn not modify `args` on failure.
template <typename... Args>
  requires(internal::CanDeserialize<Args> && ...)
[[nodiscard]] bool ReadPickleInto(base::PickleIterator& iter, Args&... args) {
  auto maybe_value = ReadValuesFromPickle<Args...>(iter);
  if (!maybe_value) {
    return false;
  }
  std::tie(args...) = std::move(maybe_value).value();
  return true;
}

namespace internal {

// Create a PickleIterator `iter` from `pickle` and call `f(iter, args)`. with
// it. If the input was completely consumed, return the result, otherwise
// return a value indicating failure (std::nullopt or false).
template <typename F, typename... Args>
std::invoke_result_t<F, base::PickleIterator&, Args&&...>
CallWithPickleIterator(const base::Pickle& pickle, F&& f, Args&&... args) {
  base::PickleIterator iter(pickle);
  auto result = std::forward<F>(f)(iter, std::forward<Args>(args)...);
  if (!iter.ReachedEnd()) {
    // This return statement will turn into std::nullopt or false as needed.
    return {};
  }
  return result;
}

}  // namespace internal

// Convenience version of ReadValueFromPickle that takes a base::Pickle
// instead of a base::PickleIterator. Expects the pickle to be completely
// consumed.
template <typename T>
  requires(internal::CanDeserialize<T>)
std::optional<T> ReadValueFromPickle(const base::Pickle& pickle) {
  // Need to specify the type to disambiguate the function pointer.
  using FunctionPointerType = std::optional<T> (*)(base::PickleIterator&);
  FunctionPointerType read_value_from_pickle = &ReadValueFromPickle<T>;
  return internal::CallWithPickleIterator(pickle, read_value_from_pickle);
}

// Convenience version of ReadValuesFromPickle that takes a base::Pickle
// instead of a base::PickleIterator. Expects the pickle to be completely
// consumed.
template <typename... Args>
  requires(internal::CanDeserialize<Args> && ...)
std::optional<std::tuple<Args...>> ReadValuesFromPickle(
    const base::Pickle& pickle) {
  // Need to specify the type to disambiguate the function pointer.
  using FunctionPointerType =
      std::optional<std::tuple<Args...>> (*)(base::PickleIterator&);
  FunctionPointerType read_values_from_pickle = &ReadValuesFromPickle<Args...>;
  return internal::CallWithPickleIterator(pickle, read_values_from_pickle);
}

// Convenience version of ReadPickleInto that takes a base::Pickle instead of
// a base::PickleIterator. Expects the pickle to be completely consumed.
template <typename... Args>
  requires(internal::CanDeserialize<Args> && ...)
[[nodiscard]] bool ReadPickleInto(const base::Pickle& pickle, Args&... args) {
  return internal::CallWithPickleIterator(pickle, &ReadPickleInto<Args...>,
                                          args...);
}

}  // namespace net

#endif  // NET_BASE_PICKLE_H_