1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8
9 #include "td/utils/common.h"
10 #include "td/utils/misc.h"
11 #include "td/utils/SharedSlice.h"
12 #include "td/utils/Slice.h"
13 #include "td/utils/SliceBuilder.h"
14 #include "td/utils/StackAllocator.h"
15 #include "td/utils/Status.h"
16 #include "td/utils/tl_parsers.h"
17 #include "td/utils/tl_storers.h"
18 #include "td/utils/Variant.h"
19
20 #include <type_traits>
21 #include <unordered_set>
22 #include <utility>
23
24 #define BEGIN_STORE_FLAGS() \
25 do { \
26 ::td::uint32 flags_store = 0; \
27 ::td::uint32 bit_offset_store = 0
28
29 #define STORE_FLAG(flag) \
30 flags_store |= (flag) << bit_offset_store; \
31 bit_offset_store++
32
33 #define END_STORE_FLAGS() \
34 CHECK(bit_offset_store < 31); \
35 ::td::store(flags_store, storer); \
36 } \
37 while (false)
38
39 #define BEGIN_PARSE_FLAGS() \
40 do { \
41 ::td::uint32 flags_parse; \
42 ::td::uint32 bit_offset_parse = 0; \
43 ::td::parse(flags_parse, parser)
44
45 #define PARSE_FLAG(flag) \
46 flag = ((flags_parse >> bit_offset_parse) & 1) != 0; \
47 bit_offset_parse++
48
49 #define END_PARSE_FLAGS() \
50 CHECK(bit_offset_parse < 31); \
51 if ((flags_parse & ~((1 << bit_offset_parse) - 1)) != 0) { \
52 parser.set_error(PSTRING() << "Invalid flags " << flags_parse << " left, current bit is " << bit_offset_parse); \
53 } \
54 } \
55 while (false)
56
57 namespace td {
58
59 template <class StorerT>
store(bool x,StorerT & storer)60 void store(bool x, StorerT &storer) {
61 storer.store_binary(static_cast<int32>(x));
62 }
63 template <class ParserT>
parse(bool & x,ParserT & parser)64 void parse(bool &x, ParserT &parser) {
65 x = parser.fetch_int() != 0;
66 }
67
68 template <class StorerT>
store(int32 x,StorerT & storer)69 void store(int32 x, StorerT &storer) {
70 storer.store_binary(x);
71 }
72 template <class ParserT>
parse(int32 & x,ParserT & parser)73 void parse(int32 &x, ParserT &parser) {
74 x = parser.fetch_int();
75 }
76
77 template <class StorerT>
store(uint32 x,StorerT & storer)78 void store(uint32 x, StorerT &storer) {
79 storer.store_binary(x);
80 }
81 template <class ParserT>
parse(uint32 & x,ParserT & parser)82 void parse(uint32 &x, ParserT &parser) {
83 x = static_cast<uint32>(parser.fetch_int());
84 }
85
86 template <class StorerT>
store(int64 x,StorerT & storer)87 void store(int64 x, StorerT &storer) {
88 storer.store_binary(x);
89 }
90 template <class ParserT>
parse(int64 & x,ParserT & parser)91 void parse(int64 &x, ParserT &parser) {
92 x = parser.fetch_long();
93 }
94 template <class StorerT>
store(uint64 x,StorerT & storer)95 void store(uint64 x, StorerT &storer) {
96 storer.store_binary(x);
97 }
98 template <class ParserT>
parse(uint64 & x,ParserT & parser)99 void parse(uint64 &x, ParserT &parser) {
100 x = static_cast<uint64>(parser.fetch_long());
101 }
102
103 template <class StorerT>
store(double x,StorerT & storer)104 void store(double x, StorerT &storer) {
105 storer.store_binary(x);
106 }
107 template <class ParserT>
parse(double & x,ParserT & parser)108 void parse(double &x, ParserT &parser) {
109 x = parser.fetch_double();
110 }
111
112 template <class StorerT>
store(Slice x,StorerT & storer)113 void store(Slice x, StorerT &storer) {
114 storer.store_string(x);
115 }
116 template <class StorerT>
store(const string & x,StorerT & storer)117 void store(const string &x, StorerT &storer) {
118 storer.store_string(x);
119 }
120 template <class StorerT>
store(const SecureString & x,StorerT & storer)121 void store(const SecureString &x, StorerT &storer) {
122 storer.store_string(x.as_slice());
123 }
124 template <class ParserT>
parse(string & x,ParserT & parser)125 void parse(string &x, ParserT &parser) {
126 x = parser.template fetch_string<string>();
127 }
128
129 template <class ParserT>
parse(SecureString & x,ParserT & parser)130 void parse(SecureString &x, ParserT &parser) {
131 x = parser.template fetch_string<SecureString>();
132 }
133
134 template <class T, class StorerT>
store(const vector<T> & vec,StorerT & storer)135 void store(const vector<T> &vec, StorerT &storer) {
136 storer.store_binary(narrow_cast<int32>(vec.size()));
137 for (auto &val : vec) {
138 store(val, storer);
139 }
140 }
141 template <class T, class StorerT>
store(const vector<T * > & vec,StorerT & storer)142 void store(const vector<T *> &vec, StorerT &storer) {
143 storer.store_binary(narrow_cast<int32>(vec.size()));
144 for (auto &val : vec) {
145 store(*val, storer);
146 }
147 }
148 template <class T, class ParserT>
parse(vector<T> & vec,ParserT & parser)149 void parse(vector<T> &vec, ParserT &parser) {
150 uint32 size = parser.fetch_int();
151 if (parser.get_left_len() < size) {
152 parser.set_error("Wrong vector length");
153 return;
154 }
155 vec = vector<T>(size);
156 for (auto &val : vec) {
157 parse(val, parser);
158 }
159 }
160
161 template <class T, class StorerT>
store(const unique_ptr<T> & ptr,StorerT & storer)162 void store(const unique_ptr<T> &ptr, StorerT &storer) {
163 CHECK(ptr != nullptr);
164 store(*ptr, storer);
165 }
166 template <class T, class ParserT>
parse(unique_ptr<T> & ptr,ParserT & parser)167 void parse(unique_ptr<T> &ptr, ParserT &parser) {
168 CHECK(ptr == nullptr);
169 ptr = make_unique<T>();
170 parse(*ptr, parser);
171 }
172
173 template <class Key, class Hash, class KeyEqual, class Allocator, class StorerT>
store(const std::unordered_set<Key,Hash,KeyEqual,Allocator> & s,StorerT & storer)174 void store(const std::unordered_set<Key, Hash, KeyEqual, Allocator> &s, StorerT &storer) {
175 storer.store_binary(narrow_cast<int32>(s.size()));
176 for (auto &val : s) {
177 store(val, storer);
178 }
179 }
180 template <class Key, class Hash, class KeyEqual, class Allocator, class ParserT>
parse(std::unordered_set<Key,Hash,KeyEqual,Allocator> & s,ParserT & parser)181 void parse(std::unordered_set<Key, Hash, KeyEqual, Allocator> &s, ParserT &parser) {
182 uint32 size = parser.fetch_int();
183 if (parser.get_left_len() < size) {
184 parser.set_error("Wrong set length");
185 return;
186 }
187 s.clear();
188 for (uint32 i = 0; i < size; i++) {
189 Key val;
190 parse(val, parser);
191 s.insert(std::move(val));
192 }
193 }
194
195 template <class U, class V, class StorerT>
store(const std::pair<U,V> & pair,StorerT & storer)196 void store(const std::pair<U, V> &pair, StorerT &storer) {
197 store(pair.first, storer);
198 store(pair.second, storer);
199 }
200 template <class U, class V, class ParserT>
parse(std::pair<U,V> & pair,ParserT & parser)201 void parse(std::pair<U, V> &pair, ParserT &parser) {
202 parse(pair.first, parser);
203 parse(pair.second, parser);
204 }
205
206 template <class T, class StorerT>
store(const T & val,StorerT & storer)207 std::enable_if_t<std::is_enum<T>::value> store(const T &val, StorerT &storer) {
208 store(static_cast<int32>(val), storer);
209 }
210 template <class T, class ParserT>
parse(T & val,ParserT & parser)211 std::enable_if_t<std::is_enum<T>::value> parse(T &val, ParserT &parser) {
212 int32 result;
213 parse(result, parser);
214 val = static_cast<T>(result);
215 }
216
217 template <class T, class StorerT>
store(const T & val,StorerT & storer)218 std::enable_if_t<!std::is_enum<T>::value> store(const T &val, StorerT &storer) {
219 val.store(storer);
220 }
221 template <class T, class ParserT>
parse(T & val,ParserT & parser)222 std::enable_if_t<!std::is_enum<T>::value> parse(T &val, ParserT &parser) {
223 val.parse(parser);
224 }
225
226 template <class... Types, class StorerT>
store(const Variant<Types...> & variant,StorerT & storer)227 void store(const Variant<Types...> &variant, StorerT &storer) {
228 store(variant.get_offset(), storer);
229 variant.visit([&storer](auto &&value) {
230 using td::store;
231 store(value, storer);
232 });
233 }
234 template <class... Types, class ParserT>
parse(Variant<Types...> & variant,ParserT & parser)235 void parse(Variant<Types...> &variant, ParserT &parser) {
236 auto type_offset = parser.fetch_int();
237 if (type_offset < 0 || type_offset >= static_cast<int32>(sizeof...(Types))) {
238 return parser.set_error("Invalid type");
239 }
240 variant.for_each([type_offset, &parser, &variant](int offset, auto *ptr) {
241 using T = std::decay_t<decltype(*ptr)>;
242 if (offset == type_offset) {
243 variant = T();
244 parse(variant.template get<T>(), parser);
245 }
246 });
247 }
248
249 template <class T>
serialize(const T & object)250 string serialize(const T &object) {
251 TlStorerCalcLength calc_length;
252 store(object, calc_length);
253 size_t length = calc_length.get_length();
254
255 string key(length, '\0');
256 if (!is_aligned_pointer<4>(key.data())) {
257 auto ptr = StackAllocator::alloc(length);
258 MutableSlice data = ptr.as_slice();
259 TlStorerUnsafe storer(data.ubegin());
260 store(object, storer);
261 CHECK(storer.get_buf() == data.uend());
262 key.assign(data.begin(), data.size());
263 } else {
264 MutableSlice data = key;
265 TlStorerUnsafe storer(data.ubegin());
266 store(object, storer);
267 CHECK(storer.get_buf() == data.uend());
268 }
269 return key;
270 }
271
272 template <class T>
serialize_secure(const T & object)273 SecureString serialize_secure(const T &object) {
274 TlStorerCalcLength calc_length;
275 store(object, calc_length);
276 size_t length = calc_length.get_length();
277
278 SecureString key(length, '\0');
279 CHECK(is_aligned_pointer<4>(key.data()));
280 MutableSlice data = key.as_mutable_slice();
281 TlStorerUnsafe storer(data.ubegin());
282 store(object, storer);
283 CHECK(storer.get_buf() == data.uend());
284 return key;
285 }
286
287 template <class T>
unserialize(T & object,Slice data)288 TD_WARN_UNUSED_RESULT Status unserialize(T &object, Slice data) {
289 TlParser parser(data);
290 parse(object, parser);
291 parser.fetch_end();
292 return parser.get_status();
293 }
294
295 } // namespace td
296