MySQL 8.4.2
Source Code Documentation
serializer_default_impl.hpp
Go to the documentation of this file.
1// Copyright (c) 2023, 2024, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
24/// @file
25/// Experimental API header
26
28
29namespace mysql::serialization {
30
31template <class Archive_concrete_type>
32template <class Field_type, Field_size field_size_defined, typename Enabler>
34 const Field_type &field) {
35 m_archive << Field_wrapper<const Field_type, field_size_defined>(field);
36 m_archive.put_field_separator();
37}
38
39template <class Archive_concrete_type>
40template <class Field_type, Field_size field_size_defined, typename Enabler>
42 Field_type &field) {
44 m_archive.process_field_separator();
45}
46
47template <class Archive_concrete_type>
48template <class Field_type, Field_size field_size_defined, typename Enabler>
50 const Field_type &field, Serializer_enum_tag) {
51 auto enumeration_value_encoded = utils::to_underlying(field);
52 using Enumeration_type = decltype(enumeration_value_encoded);
53 m_archive << Field_wrapper<Enumeration_type, field_size_defined>(
54 enumeration_value_encoded);
55 m_archive.put_field_separator();
56}
57
58template <class Archive_concrete_type>
59template <class Field_type, Field_size field_size_defined, typename Enabler>
62 auto enumeration_value_encoded = utils::to_underlying(field);
63 using Enumeration_type = decltype(enumeration_value_encoded);
65 enumeration_value_encoded);
66 auto [enumeration_value_decoded, conversion_code] =
67 mysql::utils::to_enumeration<Field_type, Enumeration_type>(
68 enumeration_value_encoded);
69 field = enumeration_value_decoded;
70 if (conversion_code == utils::Return_status::error) {
71 m_error =
72 Serialization_error(__FILE__, __LINE__, "Data integrity error",
74 }
75 m_archive.process_field_separator();
76}
77
78template <class Archive_concrete_type>
79template <class Field_type, Field_size field_size_defined, typename Enabler>
82 uint64_t encoded_size = field.size();
83 m_archive << create_varlen_field_wrapper(encoded_size);
84 using value_type = typename Field_type::value_type;
85 for (const auto &internal_field : field) {
86 m_archive.put_entry_separator();
87 // we use default size for internal fields (0)
88 encode_field<value_type, 0>(internal_field);
89 }
90 m_archive.put_field_separator();
91}
92
93template <class Archive_concrete_type>
94template <class Field_type, Field_size field_size_defined, typename Enabler>
97 uint64_t encoded_size;
98 m_archive >> create_varlen_field_wrapper(encoded_size);
99 field.clear();
100 using value_type = typename Field_type::value_type;
101 for (uint64_t internal_id = 0; internal_id < encoded_size; ++internal_id) {
102 value_type internal_field;
103 // we use default size for internal fields (0)
104 decode_field<value_type, 0>(internal_field);
105 field.push_back(internal_field);
106 m_archive.process_entry_separator();
107 }
108 m_archive.process_field_separator();
109}
110
111template <class Archive_concrete_type>
112template <class Field_type, Field_size field_size_defined, typename Enabler>
116 true);
117}
118
119template <class Archive_concrete_type>
120template <class Field_type, Field_size field_size_defined, typename Enabler>
123 // For serializable inside container, we don't check serializable id,
124 // since it must be there. Passing 0 as serializable_end_pos.
126 true);
127}
128
129template <class Archive_concrete_type>
130template <class Field_type, Field_size field_size_defined, typename Enabler>
132 const Field_type &field, Serializer_map_tag) {
133 uint64_t encoded_size = field.size();
134 m_archive << create_varlen_field_wrapper(encoded_size);
135 for (auto &pair : field) {
136 using key_type = typename Field_type::key_type;
137 using mapped_type = typename Field_type::mapped_type;
138 // cannot choose fixed number of bytes for map key type and mapped type,
139 // we use default size for internal fields (0)
140 encode_field<key_type, 0>(pair.first);
141 m_archive.put_entry_separator();
142 encode_field<mapped_type, 0>(pair.second);
143 m_archive.put_entry_separator();
144 }
145 m_archive.put_field_separator();
146}
147
148template <class Archive_concrete_type>
149template <class Field_type, Field_size field_size_defined, typename Enabler>
152 uint64_t encoded_size;
153 m_archive >> create_varlen_field_wrapper(encoded_size);
154 field.clear();
155 for (uint64_t entry_id = 0; entry_id < encoded_size; ++entry_id) {
156 using key_type = typename Field_type::key_type;
157 using mapped_type = typename Field_type::mapped_type;
159 mapped_type value;
160 // cannot choose fixed number of bytes for map key type and mapped type,
161 // we use default size for internal fields (0)
162 decode_field<key_type, 0>(key);
163 m_archive.process_entry_separator();
164 decode_field<mapped_type, 0>(value);
165 m_archive.process_entry_separator();
166 field.insert(std::make_pair(key, value));
167 }
168 m_archive.process_field_separator();
169}
170
171template <class Archive_concrete_type>
172template <class Field_type, Field_size field_size_defined, typename Enabler>
174 const Field_type &field, Serializer_set_tag) {
175 uint64_t encoded_size = field.size();
176 m_archive << create_varlen_field_wrapper(encoded_size);
177 using value_type = typename Field_type::value_type;
178 for (const auto &internal_field : field) {
179 // we use default size for internal fields (0)
180 encode_field<value_type, 0>(internal_field);
181 m_archive.put_entry_separator();
182 }
183 m_archive.put_field_separator();
184}
185
186template <class Archive_concrete_type>
187template <class Field_type, Field_size field_size_defined, typename Enabler>
190 uint64_t encoded_size;
191 m_archive >> create_varlen_field_wrapper(encoded_size);
192 using value_type = typename Field_type::value_type;
193 field.clear();
194 for (uint64_t internal_id = 0; internal_id < encoded_size; ++internal_id) {
195 value_type internal_field;
196 // we use default size for internal fields (0)
197 decode_field<value_type, 0>(internal_field);
198 field.emplace(internal_field);
199 m_archive.process_entry_separator();
200 }
201 m_archive.process_field_separator();
202}
203
204template <class Archive_concrete_type>
205template <class Field_type, Field_size field_size_defined, typename Enabler>
207 const Field_type &field, Serializer_array_tag) {
208 using value_type = std::remove_reference_t<decltype(
209 *std::begin(std::declval<Field_type &>()))>;
210 for (const auto &internal_field : field) {
211 // we use default size for internal fields (0)
212 encode_field<value_type, 0>(internal_field);
213 m_archive.put_entry_separator();
214 }
215 m_archive.put_field_separator();
216}
217
218template <class Archive_concrete_type>
219template <class Field_type, Field_size field_size_defined, typename Enabler>
222 using value_type = std::remove_reference_t<decltype(
223 *std::begin(std::declval<Field_type &>()))>;
224 for (auto &internal_field : field) {
225 // we use default size for internal fields (0)
226 decode_field<value_type, 0>(internal_field);
227 m_archive.process_entry_separator();
228 }
229 m_archive.process_field_separator();
230}
231
232template <class Archive_concrete_type>
233template <class Field_type, Field_size field_size_defined, typename Enabler>
235 const Field_type &field) {
236 return Archive_concrete_type::template get_size(
238}
239
240template <class Archive_concrete_type>
241template <class Field_type, Field_size field_size_defined, typename Enabler>
243 const Field_type &field, Serializer_enum_tag) {
244 auto enumeration_value_encoded = utils::to_underlying(field);
245 using Enumeration_type = decltype(enumeration_value_encoded);
246 return get_field_size<Enumeration_type, field_size_defined>(
247 enumeration_value_encoded);
248}
249
250template <class Archive_concrete_type>
251template <class Field_type, Field_size field_size_defined, typename Enabler>
254 std::size_t field_size = 0;
255 using value_type = typename Field_type::value_type;
256 uint64_t encoded_size = field.size();
257 field_size += get_field_size<uint64_t, 0>(encoded_size);
258 for (const auto &internal_field : field) {
259 field_size += get_field_size<value_type, 0>(internal_field);
260 }
261 return field_size;
262}
263
264template <class Archive_concrete_type>
265template <class Field_type, Field_size field_size_defined, typename Enabler>
269 0, field, true);
270}
271
272template <class Archive_concrete_type>
273template <class Field_type, Field_size field_size_defined, typename Enabler>
275 const Field_type &field, Serializer_map_tag) {
276 using key_type = typename Field_type::key_type;
277 using mapped_type = typename Field_type::mapped_type;
278 std::size_t field_size = 0;
279 uint64_t encoded_size = field.size();
280 field_size += get_field_size<uint64_t, 0>(encoded_size);
281 for (auto &pair : field) {
282 field_size += get_field_size<key_type, 0>(pair.first);
283 field_size += get_field_size<mapped_type, 0>(pair.second);
284 }
285 return field_size;
286}
287
288template <class Archive_concrete_type>
289template <class Field_type, Field_size field_size_defined, typename Enabler>
291 const Field_type &field, Serializer_set_tag) {
292 std::size_t field_size = 0;
293 uint64_t encoded_size = field.size();
294 field_size += get_field_size<uint64_t, 0>(encoded_size);
295 using value_type = typename Field_type::value_type;
296 for (const auto &internal_field : field) {
297 field_size += get_field_size<value_type, 0>(internal_field);
298 }
299 return field_size;
300}
301
302template <class Archive_concrete_type>
303template <class Field_type, Field_size field_size_defined, typename Enabler>
305 const Field_type &field, Serializer_array_tag) {
306 std::size_t field_size = 0;
307 using value_type = std::remove_reference_t<decltype(
308 *std::begin(std::declval<Field_type &>()))>;
309 for (const auto &internal_field : field) {
310 field_size += get_field_size<value_type, 0>(internal_field);
311 }
312 return field_size;
313}
314
315template <class Archive_concrete_type>
316template <class Field_type, Field_size field_size_defined>
319 const Field_definition<Field_type, field_size_defined> &field_definition) {
320 bool is_provided = false;
321 if (this->is_good() == true) {
322 is_provided = field_definition.run_encode_predicate();
323 if (is_provided) {
324 for (size_t level_id = 0; level_id < level; ++level_id) {
325 m_archive.put_level_separator();
326 }
328 m_archive.put_entry_separator();
329 }
330 }
331 return is_provided;
332}
333
334template <class Archive_concrete_type>
335template <class Field_type, Field_size field_size_defined>
339 bool is_provided = false;
340 if (this->is_good() == true) {
341 is_provided = true;
342 for (size_t level_id = 0; level_id < level; ++level_id) {
343 m_archive.process_level_separator();
344 }
345 Field_id_type field_type_read;
346 m_archive.peek(create_varlen_field_wrapper(field_type_read));
347 if (field_id != field_type_read || this->is_good() == false) {
348 field_definition.run_field_missing();
349 is_provided = false;
350 }
351 if (is_provided) {
352 m_archive >> create_varlen_field_wrapper(field_type_read);
353 m_archive.process_entry_separator();
354 }
355 }
356 return is_provided;
357}
358
359template <class Archive_concrete_type>
360template <class Field_type, Field_size field_size_defined>
363 const Field_definition<Field_type, field_size_defined> &field_definition) {
364 bool is_provided = encode_field_id(level, field_id, field_definition);
365 if (is_provided) {
366 encode_field<Field_type, field_size_defined>(field_definition.get_ref());
367 }
368}
369
370template <class Archive_concrete_type>
371template <class Field_type, Field_size field_size_defined>
373 Level_type level, Field_id_type field_id, std::size_t serializable_end_pos,
375 // serializable_end_pos = 0 is a marker for serializers that don't check end
376 // pos
377 if (m_archive.get_read_pos() == serializable_end_pos &&
378 serializable_end_pos != 0) { // reached the end
379 // missing field handling here
380 field_definition.run_field_missing();
381 return;
382 }
383 bool is_provided = decode_field_id(level, field_id, field_definition);
384 if (is_provided) {
385 decode_field<Field_type, field_size_defined>(field_definition.get_ref());
386 }
387}
388
389template <class Serializable_type>
391 const Serializable_type &serializable) {
392 Field_id_type last_non_ignorable_field_id = 0;
393 auto func_s = [&last_non_ignorable_field_id](const auto &nested,
394 auto nested_id) {
395 if (nested.is_any_field_provided() && nested.is_ignorable() == false) {
396 last_non_ignorable_field_id = nested_id + 1;
397 }
398 };
399 auto func_f = [&last_non_ignorable_field_id](
400 const auto &field, auto processed_field_id) -> auto {
401 if (field.run_encode_predicate() && field.is_field_ignorable() == false) {
402 last_non_ignorable_field_id = processed_field_id + 1;
403 }
404 };
405 serializable.do_for_each_field(func_s, func_f);
406 return last_non_ignorable_field_id;
407}
408
409template <class Archive_concrete_type>
410template <class Serializable_type>
412 Level_type, Field_id_type field_id, const Serializable_type &serializable,
413 bool skip_id) {
414 using Serializer_type = Serializer_default<Archive_concrete_type>;
415
416 uint64_t encoded_size =
417 Serializer_type::get_size_serializable(field_id, serializable, skip_id);
418
419 Field_id_type last_non_ignorable_field_id =
421
422 if (skip_id == false) {
424 m_archive.put_field_separator();
425 }
426 m_archive << create_varlen_field_wrapper(encoded_size);
427 m_archive.put_field_separator();
428 m_archive << create_varlen_field_wrapper(last_non_ignorable_field_id);
429 m_archive.put_field_separator();
430}
431
432template <class Archive_concrete_type>
433template <class Serializable_type>
434std::size_t
436 Level_type, Field_id_type field_id, Serializable_type &serializable,
437 bool skip_id) {
438 uint64_t encoded_size = 0;
439 Field_id_type last_non_ignorable_field_id = 0;
440 if (skip_id == false) {
441 Field_id_type field_type_read;
442 m_archive >> create_varlen_field_wrapper(field_type_read);
443 m_archive.process_field_separator();
444 if (field_type_read != field_id || this->is_good() == false) {
445 m_error =
446 Serialization_error(__FILE__, __LINE__, "Missing field id",
448 }
449 }
450
451 if (this->is_good()) {
452 auto last_known_field_id = serializable.get_last_field_id();
453 m_archive >> create_varlen_field_wrapper(encoded_size);
454 m_archive.process_field_separator();
455 m_archive >> create_varlen_field_wrapper(last_non_ignorable_field_id);
456 m_archive.process_field_separator();
457
458 if (last_known_field_id + 1 < last_non_ignorable_field_id) {
459 m_error = Serialization_error(
460 __FILE__, __LINE__,
461 "Unknown, non ignorable fields found in the data stream.",
463 }
464 }
465 return static_cast<std::size_t>(encoded_size);
466}
467
468template <class Archive_concrete_type>
469template <class Field_type, Field_size field_size_defined>
472 const Field_definition<Field_type, field_size_defined> &field_definition) {
473 std::size_t calculated_size = 0;
474 bool is_provided = field_definition.run_encode_predicate();
475 if (is_provided) {
476 auto size_id_type = Archive_concrete_type::template get_size(
478 calculated_size = get_field_size<Field_type, field_size_defined>(
479 field_definition.get_ref()) +
480 size_id_type;
481 }
482 return calculated_size;
483}
484
485template <class Archive_concrete_type>
486template <class Serializable_concrete_type>
488 Field_id_type field_id, const Serializable_concrete_type &serializable,
489 bool skip_id) {
490 std::size_t serializable_overhead_type = 0;
491 if (skip_id == false) {
492 serializable_overhead_type = Archive_concrete_type::template get_size(
494 }
495 auto serializable_size = serializable.template get_size_internal<Base_type>();
496 auto serializable_overhead_size = Archive_concrete_type::template get_size(
497 create_varlen_field_wrapper(serializable_size));
498
499 Field_id_type last_non_ignorable_field_id =
501
502 auto serializable_overhead_last_non_ignorable_field_id =
503 Archive_concrete_type::template get_size(
504 create_varlen_field_wrapper(last_non_ignorable_field_id));
505 return serializable_overhead_type + serializable_overhead_size +
506 serializable_overhead_last_non_ignorable_field_id + serializable_size;
507}
508
509} // namespace mysql::serialization
Field definition provided by classes implementing Serializable interface.
Definition: field_definition.h:45
Field_type & get_ref()
Definition: field_definition.h:101
void run_field_missing() const
Runs "field missing functor" in case field is not available in the provided encoded data.
Definition: field_definition.h:106
bool run_encode_predicate() const
Runs encode predicate functor.
Definition: field_definition.h:110
Wrapper for fields to hold field reference and user-defined, compile-time field size.
Definition: field_wrapper.h:43
Error used internally in serialization framework.
Definition: serialization_error.h:46
Basic serializer that is implementing Serializer interface.
Definition: serializer_default.h:63
static std::size_t get_size_field_def(Field_id_type field_id, const Field_definition< Field_type, field_size_defined > &field_definition)
Function returns size of serialized field_definition object.
Definition: serializer_default_impl.hpp:470
static std::size_t get_field_size(const Field_type &field)
Function used internally to calculate size of fields, version for basic types.
Definition: serializer_default_impl.hpp:234
void encode(Level_type level, Field_id_type field_id, const Field_definition< Field_type, field_size_defined > &field_definition)
Function used to encode one field.
Definition: serializer_default_impl.hpp:361
bool encode_field_id(Level_type level, Field_id_type field_id, const Field_definition< Field_type, field_size_defined > &field_definition)
Function used internally to encode field_id and handle optional fields.
Definition: serializer_default_impl.hpp:317
bool decode_field_id(Level_type level, Field_id_type field_id, Field_definition< Field_type, field_size_defined > &field_definition)
Function used internally to decode field_id and handle optional fields.
Definition: serializer_default_impl.hpp:336
void decode_field(Field_type &field)
Function used internally to decode field_id and handle optional fields, version for basic types.
Definition: serializer_default_impl.hpp:41
static std::size_t get_size_serializable(Field_id_type field_id, const Serializable_concrete_type &serializable, bool skip_id=false)
Function returns size of serialized field_definition object.
Definition: serializer_default_impl.hpp:487
void decode(Level_type level, Field_id_type field_id, std::size_t serializable_end_pos, Field_definition< Field_type, field_size_defined > &field_definition)
Function used to decode one field.
Definition: serializer_default_impl.hpp:372
std::size_t decode_serializable_metadata(Level_type level, Field_id_type field_id, Serializable_type &serializable, bool skip_id)
This function loads serializable metadata.
Definition: serializer_default_impl.hpp:435
void encode_field(const Field_type &field)
Function used internally to encode field_id and handle optional fields, version for basic types.
Definition: serializer_default_impl.hpp:33
void encode_serializable_metadata(Level_type level, Field_id_type field_id, const Serializable_type &serializable, bool skip_id)
This function saves serializable metadata.
Definition: serializer_default_impl.hpp:411
void encode_serializable(Level_type level, Field_id_type field_id, const Serializable_type &serializable, bool skip_id)
Function used to encode serializable field, this function saves serializable metadata and calls seria...
Definition: serializer_impl.hpp:118
void decode_serializable(Level_type level, Field_id_type field_id, std::size_t serializable_end_pos, Serializable_type &serializable, bool skip_id)
Function used to decode serializable field, this function loads serializable metadata and calls seria...
Definition: serializer_impl.hpp:158
uint16_t value_type
Definition: vt100.h:184
int key_type
Definition: method.h:38
Definition: archive.h:37
Field_id_type find_last_non_ignorable_field_id(const Serializable_type &serializable)
Definition: serializer_default_impl.hpp:390
std::size_t Level_type
Type of the "level" used to indicate on which level of the nested message internal fields are defined...
Definition: serialization_types.h:40
uint64_t Field_id_type
Type for field_id assigned to each field in the.
Definition: serialization_types.h:42
auto create_varlen_field_wrapper(Field_type &field_reference)
Definition: field_wrapper.h:85
@ unknown_field
unknown field found in the data stream
@ data_integrity_error
corrupted data, unexpected value found
@ field_id_mismatch
field id read does not match expected field id
@ error
operation failed
constexpr decltype(auto) to_underlying(Enum_type enum_value)
Helper function that converts enum type to underlying integer type.
Definition: enumeration_utils.h:44
const char * begin(const char *const c)
Definition: base64.h:44
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Experimental API header.
static const LEX_CSTRING field_id
Definition: sql_show_processlist.cc:49
Definition: sql_resultset.h:36
Helper tag for array types to help compiler pick the correct method.
Definition: serializer_default.h:49
Helper tag for enum types to help compiler pick the correct method.
Definition: serializer_default.h:45
Helper tag for map types to help compiler pick the correct method.
Definition: serializer_default.h:47
Helper tag for serializable types to help compiler pick the correct method.
Definition: serializer_default.h:54
Helper tag for set types to help compiler pick the correct method.
Definition: serializer_default.h:51
Helper tag for vector types to help compiler pick the correct method.
Definition: serializer_default.h:43