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