1 #pragma once
2
3 #include "traits.hpp"
4
5 namespace tf {
6
7 // ----------------------------------------------------------------------------
8 // Supported C++ STL type
9 // ----------------------------------------------------------------------------
10
11 // std::basic_string
12 template <typename T>
13 struct is_std_basic_string : std::false_type {};
14
15 template <typename... ArgsT>
16 struct is_std_basic_string <std::basic_string<ArgsT...>> : std::true_type {};
17
18 template <typename T>
19 constexpr bool is_std_basic_string_v = is_std_basic_string<T>::value;
20
21 // std::array
22 template <typename T>
23 struct is_std_array : std::false_type {};
24
25 template <typename T, size_t N>
26 struct is_std_array <std::array<T, N>> : std::true_type {};
27
28 template <typename T>
29 constexpr bool is_std_array_v = is_std_array<T>::value;
30
31 // std::vector
32 template <typename T>
33 struct is_std_vector : std::false_type {};
34
35 template <typename... ArgsT>
36 struct is_std_vector <std::vector<ArgsT...>> : std::true_type {};
37
38 template <typename T>
39 constexpr bool is_std_vector_v = is_std_vector<T>::value;
40
41 // std::deque
42 template <typename T>
43 struct is_std_deque : std::false_type {};
44
45 template <typename... ArgsT>
46 struct is_std_deque <std::deque<ArgsT...>> : std::true_type {};
47
48 template <typename T>
49 constexpr bool is_std_deque_v = is_std_deque<T>::value;
50
51 // std::list
52 template <typename T>
53 struct is_std_list : std::false_type {};
54
55 template <typename... ArgsT>
56 struct is_std_list <std::list<ArgsT...>> : std::true_type {};
57
58 template <typename T>
59 constexpr bool is_std_list_v = is_std_list<T>::value;
60
61 // std::forward_list
62 template <typename T>
63 struct is_std_forward_list : std::false_type {};
64
65 template <typename... ArgsT>
66 struct is_std_forward_list <std::forward_list<ArgsT...>> : std::true_type {};
67
68 template <typename T>
69 constexpr bool is_std_forward_list_v = is_std_forward_list<T>::value;
70
71 // std::map
72 template <typename T>
73 struct is_std_map : std::false_type {};
74
75 template <typename... ArgsT>
76 struct is_std_map <std::map<ArgsT...>> : std::true_type {};
77
78 template <typename T>
79 constexpr bool is_std_map_v = is_std_map<T>::value;
80
81 // std::unordered_map
82 template <typename T>
83 struct is_std_unordered_map : std::false_type {};
84
85 template <typename... ArgsT>
86 struct is_std_unordered_map <std::unordered_map<ArgsT...>> : std::true_type {};
87
88 template <typename T>
89 constexpr bool is_std_unordered_map_v = is_std_unordered_map<T>::value;
90
91 // std::set
92 template <typename T>
93 struct is_std_set : std::false_type {};
94
95 template <typename... ArgsT>
96 struct is_std_set <std::set<ArgsT...>> : std::true_type {};
97
98 template <typename T>
99 constexpr bool is_std_set_v = is_std_set<T>::value;
100
101 // std::unordered_set
102 template <typename T>
103 struct is_std_unordered_set : std::false_type {};
104
105 template <typename... ArgsT>
106 struct is_std_unordered_set <std::unordered_set<ArgsT...>> : std::true_type {};
107
108 template <typename T>
109 constexpr bool is_std_unordered_set_v = is_std_unordered_set<T>::value;
110
111 // std::variant
112 template <typename T>
113 struct is_std_variant : std::false_type {};
114
115 template <typename... ArgsT>
116 struct is_std_variant <std::variant<ArgsT...>> : std::true_type {};
117
118 template <typename T>
119 constexpr bool is_std_variant_v = is_std_variant<T>::value;
120
121 // std::optional
122 template <typename T>
123 struct is_std_optional : std::false_type {};
124
125 template <typename... ArgsT>
126 struct is_std_optional <std::optional<ArgsT...>> : std::true_type {};
127
128 template <typename T>
129 constexpr bool is_std_optional_v = is_std_optional<T>::value;
130
131 // std::unique_ptr
132 template <typename T>
133 struct is_std_unique_ptr : std::false_type {};
134
135 template <typename... ArgsT>
136 struct is_std_unique_ptr <std::unique_ptr<ArgsT...>> : std::true_type {};
137
138 template <typename T>
139 constexpr bool is_std_unique_ptr_v = is_std_unique_ptr<T>::value;
140
141 // std::shared_ptr
142 template <typename T>
143 struct is_std_shared_ptr : std::false_type {};
144
145 template <typename... ArgsT>
146 struct is_std_shared_ptr <std::shared_ptr<ArgsT...>> : std::true_type {};
147
148 template <typename T>
149 constexpr bool is_std_shared_ptr_v = is_std_shared_ptr<T>::value;
150
151 // std::duration
152 template <typename T> struct is_std_duration : std::false_type {};
153
154 template <typename... ArgsT>
155 struct is_std_duration<std::chrono::duration<ArgsT...>> : std::true_type {};
156
157 template <typename T>
158 constexpr bool is_std_duration_v = is_std_duration<T>::value;
159
160 // std::time_point
161 template <typename T>
162 struct is_std_time_point : std::false_type {};
163
164 template <typename... ArgsT>
165 struct is_std_time_point<std::chrono::time_point<ArgsT...>> : std::true_type {};
166
167 template <typename T>
168 constexpr bool is_std_time_point_v = is_std_time_point<T>::value;
169
170 // std::tuple
171 template <typename T>
172 struct is_std_tuple : std::false_type {};
173
174 template <typename... ArgsT>
175 struct is_std_tuple<std::tuple<ArgsT...>> : std::true_type {};
176
177 template <typename T>
178 constexpr bool is_std_tuple_v = is_std_tuple<T>::value;
179
180 //-----------------------------------------------------------------------------
181 // Type extraction.
182 //-----------------------------------------------------------------------------
183
184 // ExtractType: forward declaration
185 template <size_t, typename>
186 struct ExtractType;
187
188 // ExtractType_t: alias interface
189 template <size_t idx, typename C>
190 using ExtractType_t = typename ExtractType<idx, C>::type;
191
192 // ExtractType: base
193 template <template <typename...> typename C, typename T, typename... RestT>
194 struct ExtractType <0, C<T, RestT...>> {
195 using type = T;
196 };
197
198 // ExtractType: base
199 template <typename T>
200 struct ExtractType <0, T> {
201 using type = T;
202 };
203
204 // ExtractType: recursive definition.
205 template <size_t idx, template <typename...> typename C, typename T, typename... RestT>
206 struct ExtractType <idx, C<T, RestT...>> : ExtractType<idx-1, C<RestT...>> {
207 };
208
209 // ----------------------------------------------------------------------------
210 // Size Wrapper
211 // ----------------------------------------------------------------------------
212
213 // Struct: SizeTag
214 // Class that wraps a given size item which can be customized.
215 template <typename T>
216 class SizeTag {
217
218 public:
219
220 using type = std::conditional_t<std::is_lvalue_reference_v<T>, T, std::decay_t<T>>;
221
SizeTag(T && item)222 SizeTag(T&& item) : _item(std::forward<T>(item)) {}
223
224 SizeTag& operator = (const SizeTag&) = delete;
225
get() const226 inline const T& get() const {return _item;}
227
228 template <typename ArchiverT>
save(ArchiverT & ar) const229 auto save(ArchiverT & ar) const { return ar(_item); }
230
231 template <typename ArchiverT>
load(ArchiverT & ar)232 auto load(ArchiverT & ar) { return ar(_item); }
233
234 private:
235
236 type _item;
237 };
238
239 // Function: make_size_tag
240 template <typename T>
make_size_tag(T && t)241 SizeTag<T> make_size_tag(T&& t) {
242 return { std::forward<T>(t) };
243 }
244
245 // ----------------------------------------------------------------------------
246 // Size Wrapper
247 // ----------------------------------------------------------------------------
248
249 // Class: MapItem
250 template <typename KeyT, typename ValueT>
251 class MapItem {
252
253 public:
254
255 using KeyType = std::conditional_t <std::is_lvalue_reference_v<KeyT>, KeyT, std::decay_t<KeyT>>;
256 using ValueType = std::conditional_t <std::is_lvalue_reference_v<ValueT>, ValueT, std::decay_t<ValueT>>;
257
MapItem(KeyT && k,ValueT && v)258 MapItem(KeyT&& k, ValueT&& v) : _key(std::forward<KeyT>(k)), _value(std::forward<ValueT>(v)) {}
259 MapItem& operator = (const MapItem&) = delete;
260
key() const261 inline const KeyT& key() const { return _key; }
value() const262 inline const ValueT& value() const { return _value; }
263
264 template <typename ArchiverT>
save(ArchiverT & ar) const265 auto save(ArchiverT & ar) const { return ar(_key, _value); }
266
267 template <typename ArchiverT>
load(ArchiverT & ar)268 auto load(ArchiverT & ar) { return ar(_key, _value); }
269
270 private:
271
272 KeyType _key;
273 ValueType _value;
274 };
275
276 // Function: make_kv_pair
277 template <typename KeyT, typename ValueT>
make_kv_pair(KeyT && k,ValueT && v)278 MapItem<KeyT, ValueT> make_kv_pair(KeyT&& k, ValueT&& v) {
279 return { std::forward<KeyT>(k), std::forward<ValueT>(v) };
280 }
281
282 // ----------------------------------------------------------------------------
283 // Serializer Definition
284 // ----------------------------------------------------------------------------
285
286 template <typename T>
287 constexpr auto is_default_serializable_v = (
288 std::is_arithmetic_v<T> ||
289 std::is_enum_v<T> ||
290 is_std_basic_string_v<T> ||
291 is_std_vector_v<T> ||
292 is_std_deque_v<T> ||
293 is_std_list_v<T> ||
294 is_std_forward_list_v<T> ||
295 is_std_map_v<T> ||
296 is_std_unordered_map_v<T> ||
297 is_std_set_v<T> ||
298 is_std_unordered_set_v<T> ||
299 is_std_duration_v<T> ||
300 is_std_time_point_v<T> ||
301 is_std_variant_v<T> ||
302 is_std_optional_v<T> ||
303 is_std_tuple_v<T> ||
304 is_std_array_v<T>
305 );
306
307
308 // Class: Serializer
309 template <typename Stream, typename SizeType = std::streamsize>
310 class Serializer {
311
312 public:
313
314 Serializer(Stream& stream);
315
316 template <typename... T>
317 SizeType operator()(T&&... items);
318
319 private:
320
321 Stream& _stream;
322
323 template <typename T,
324 std::enable_if_t<!is_default_serializable_v<std::decay_t<T>>, void>* = nullptr
325 >
326 SizeType _save(T&&);
327
328 template <typename T,
329 std::enable_if_t<std::is_arithmetic_v<std::decay_t<T>>, void>* = nullptr
330 >
331 SizeType _save(T&&);
332
333 template <typename T,
334 std::enable_if_t<is_std_basic_string_v<std::decay_t<T>>, void>* = nullptr
335 >
336 SizeType _save(T&&);
337
338 template <typename T,
339 std::enable_if_t<is_std_vector_v<std::decay_t<T>>, void>* = nullptr
340 >
341 SizeType _save(T&&);
342
343 template <typename T,
344 std::enable_if_t<
345 is_std_deque_v<std::decay_t<T>> ||
346 is_std_list_v<std::decay_t<T>>,
347 void
348 >* = nullptr
349 >
350 SizeType _save(T&&);
351
352 template <typename T,
353 std::enable_if_t<
354 is_std_forward_list_v<std::decay_t<T>>,
355 void
356 >* = nullptr
357 >
358 SizeType _save(T&&);
359
360 template <typename T,
361 std::enable_if_t<
362 is_std_map_v<std::decay_t<T>> ||
363 is_std_unordered_map_v<std::decay_t<T>>,
364 void
365 >* = nullptr
366 >
367 SizeType _save(T&&);
368
369 template <typename T,
370 std::enable_if_t<
371 is_std_set_v<std::decay_t<T>> ||
372 is_std_unordered_set_v<std::decay_t<T>>,
373 void
374 >* = nullptr
375 >
376 SizeType _save(T&&);
377
378 template <typename T,
379 std::enable_if_t<std::is_enum_v<std::decay_t<T>>, void>* = nullptr
380 >
381 SizeType _save(T&&);
382
383 template <typename T,
384 std::enable_if_t<is_std_duration_v<std::decay_t<T>>, void>* = nullptr
385 >
386 SizeType _save(T&&);
387
388 template <typename T,
389 std::enable_if_t<is_std_time_point_v<std::decay_t<T>>, void>* = nullptr
390 >
391 SizeType _save(T&&);
392
393 template <typename T,
394 std::enable_if_t<is_std_optional_v<std::decay_t<T>>, void>* = nullptr
395 >
396 SizeType _save(T&&);
397
398 template <typename T,
399 std::enable_if_t<is_std_variant_v<std::decay_t<T>>, void>* = nullptr
400 >
401 SizeType _save(T&&);
402
403 template <typename T,
404 std::enable_if_t<is_std_tuple_v<std::decay_t<T>>, void>* = nullptr
405 >
406 SizeType _save(T&&);
407
408 template <typename T,
409 std::enable_if_t<is_std_array_v<std::decay_t<T>>, void>* = nullptr
410 >
411 SizeType _save(T&&);
412
413
414 };
415
416 // Constructor
417 template <typename Stream, typename SizeType>
Serializer(Stream & stream)418 Serializer<Stream, SizeType>::Serializer(Stream& stream) : _stream(stream) {
419 }
420
421 // Operator ()
422 template <typename Stream, typename SizeType>
423 template <typename... T>
operator ()(T &&...items)424 SizeType Serializer<Stream, SizeType>::operator() (T&&... items) {
425 return (_save(std::forward<T>(items)) + ...);
426 }
427
428 // arithmetic data type
429 template <typename Stream, typename SizeType>
430 template <typename T,
431 std::enable_if_t<std::is_arithmetic_v<std::decay_t<T>>, void>*
432 >
_save(T && t)433 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
434 _stream.write(reinterpret_cast<const char*>(std::addressof(t)), sizeof(t));
435 return sizeof(t);
436 }
437
438 // std::basic_string
439 template <typename Stream, typename SizeType>
440 template <typename T,
441 std::enable_if_t<is_std_basic_string_v<std::decay_t<T>>, void>*
442 >
_save(T && t)443 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
444 using U = std::decay_t<T>;
445 auto sz = _save(make_size_tag(t.size()));
446 _stream.write(
447 reinterpret_cast<const char*>(t.data()),
448 t.size()*sizeof(typename U::value_type)
449 );
450 return sz + t.size()*sizeof(typename U::value_type);
451 }
452
453 // std::vector
454 template <typename Stream, typename SizeType>
455 template <typename T,
456 std::enable_if_t<is_std_vector_v<std::decay_t<T>>, void>*
457 >
_save(T && t)458 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
459
460 using U = std::decay_t<T>;
461
462 auto sz = _save(make_size_tag(t.size()));
463
464 if constexpr (std::is_arithmetic_v<typename U::value_type>) {
465 _stream.write(
466 reinterpret_cast<const char*>(t.data()),
467 t.size() * sizeof(typename U::value_type)
468 );
469 sz += t.size() * sizeof(typename U::value_type);
470 } else {
471 for(auto&& item : t) {
472 sz += _save(item);
473 }
474 }
475
476 return sz;
477 }
478
479 // std::list and std::deque
480 template <typename Stream, typename SizeType>
481 template <typename T,
482 std::enable_if_t<is_std_deque_v<std::decay_t<T>> ||
483 is_std_list_v<std::decay_t<T>>, void>*
484 >
_save(T && t)485 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
486 auto sz = _save(make_size_tag(t.size()));
487 for(auto&& item : t) {
488 sz += _save(item);
489 }
490 return sz;
491 }
492
493 // std::forward_list
494 template <typename Stream, typename SizeType>
495 template <typename T,
496 std::enable_if_t<is_std_forward_list_v<std::decay_t<T>>, void>*
497 >
_save(T && t)498 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
499 auto sz = _save(make_size_tag(std::distance(t.begin(), t.end())));
500 for(auto&& item : t) {
501 sz += _save(item);
502 }
503 return sz;
504 }
505
506 // std::map and std::unordered_map
507 template <typename Stream, typename SizeType>
508 template <typename T, std::enable_if_t<
509 is_std_map_v<std::decay_t<T>> ||
510 is_std_unordered_map_v<std::decay_t<T>>,
511 void
512 >*>
_save(T && t)513 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
514 auto sz = _save(make_size_tag(t.size()));
515 for(auto&& [k, v] : t) {
516 sz += _save(make_kv_pair(k, v));
517 }
518 return sz;
519 }
520
521 // std::set and std::unordered_set
522 template <typename Stream, typename SizeType>
523 template <typename T, std::enable_if_t<
524 is_std_set_v<std::decay_t<T>> ||
525 is_std_unordered_set_v<std::decay_t<T>>,
526 void
527 >*>
_save(T && t)528 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
529 auto sz = _save(make_size_tag(t.size()));
530 for(auto&& item : t) {
531 sz += _save(item);
532 }
533 return sz;
534 }
535
536 // enum data type
537 template <typename Stream, typename SizeType>
538 template <typename T,
539 std::enable_if_t<std::is_enum_v<std::decay_t<T>>, void>*
540 >
_save(T && t)541 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
542 using U = std::decay_t<T>;
543 return _save(static_cast<std::underlying_type_t<U>>(t));
544 }
545
546 // duration data type
547 template <typename Stream, typename SizeType>
548 template <typename T,
549 std::enable_if_t<is_std_duration_v<std::decay_t<T>>, void>*
550 >
_save(T && t)551 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
552 return _save(t.count());
553 }
554
555 // time point data type
556 template <typename Stream, typename SizeType>
557 template <typename T,
558 std::enable_if_t<is_std_time_point_v<std::decay_t<T>>, void>*
559 >
_save(T && t)560 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
561 return _save(t.time_since_epoch());
562 }
563
564 // optional data type
565 template <typename Stream, typename SizeType>
566 template <typename T,
567 std::enable_if_t<is_std_optional_v<std::decay_t<T>>, void>*
568 >
_save(T && t)569 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
570 if(bool flag = t.has_value(); flag) {
571 return _save(flag) + _save(*t);
572 }
573 else {
574 return _save(flag);
575 }
576 }
577
578 // variant type
579 template <typename Stream, typename SizeType>
580 template <typename T,
581 std::enable_if_t<is_std_variant_v<std::decay_t<T>>, void>*
582 >
_save(T && t)583 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
584 return _save(t.index()) +
585 std::visit([&] (auto&& arg){ return _save(arg);}, t);
586 }
587
588 // tuple type
589 template <typename Stream, typename SizeType>
590 template <typename T,
591 std::enable_if_t<is_std_tuple_v<std::decay_t<T>>, void>*
592 >
_save(T && t)593 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
594 return std::apply(
595 [&] (auto&&... args) {
596 return (_save(std::forward<decltype(args)>(args)) + ... + 0);
597 },
598 std::forward<T>(t)
599 );
600 }
601
602 // array
603 template <typename Stream, typename SizeType>
604 template <typename T,
605 std::enable_if_t<is_std_array_v<std::decay_t<T>>, void>*
606 >
_save(T && t)607 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
608
609 using U = std::decay_t<T>;
610
611 static_assert(std::tuple_size<U>::value > 0, "Array size can't be zero");
612
613 SizeType sz;
614
615 if constexpr(std::is_arithmetic_v<typename U::value_type>) {
616 _stream.write(reinterpret_cast<const char*>(t.data()), sizeof(t));
617 sz = sizeof(t);
618 }
619 else {
620 sz = 0;
621 for(auto&& item : t) {
622 sz += _save(item);
623 }
624 }
625
626 return sz;
627 }
628
629 // custom save method
630 template <typename Stream, typename SizeType>
631 template <typename T,
632 std::enable_if_t<!is_default_serializable_v<std::decay_t<T>>, void>*
633 >
_save(T && t)634 SizeType Serializer<Stream, SizeType>::_save(T&& t) {
635 return t.save(*this);
636 }
637
638 // ----------------------------------------------------------------------------
639 // DeSerializer Definition
640 // ----------------------------------------------------------------------------
641
642 template <typename T>
643 constexpr auto is_default_deserializable_v =
644 std::is_arithmetic_v<T> ||
645 std::is_enum_v<T> ||
646 is_std_basic_string_v<T> ||
647 is_std_vector_v<T> ||
648 is_std_deque_v<T> ||
649 is_std_list_v<T> ||
650 is_std_forward_list_v<T> ||
651 is_std_map_v<T> ||
652 is_std_unordered_map_v<T> ||
653 is_std_set_v<T> ||
654 is_std_unordered_set_v<T> ||
655 is_std_duration_v<T> ||
656 is_std_time_point_v<T> ||
657 is_std_variant_v<T> ||
658 is_std_optional_v<T> ||
659 is_std_tuple_v<T> ||
660 is_std_array_v<T>;
661
662 // Class: Deserializer
663 template <typename Stream, typename SizeType = std::streamsize>
664 class Deserializer {
665
666 public:
667
668 Deserializer(Stream& stream);
669
670 template <typename... T>
671 SizeType operator()(T&&... items);
672
673 private:
674
675 Stream& _stream;
676
677 // Function: _variant_helper
678 template <
679 size_t I = 0, typename... ArgsT,
680 std::enable_if_t<I==sizeof...(ArgsT)>* = nullptr
681 >
682 SizeType _variant_helper(size_t, std::variant<ArgsT...>&);
683
684 // Function: _variant_helper
685 template <
686 size_t I = 0, typename... ArgsT,
687 std::enable_if_t<I<sizeof...(ArgsT)>* = nullptr
688 >
689 SizeType _variant_helper(size_t, std::variant<ArgsT...>&);
690
691 template <typename T,
692 std::enable_if_t<std::is_arithmetic_v<std::decay_t<T>>, void>* = nullptr
693 >
694 SizeType _load(T&&);
695
696 template <typename T,
697 std::enable_if_t<is_std_basic_string_v<std::decay_t<T>>, void>* = nullptr
698 >
699 SizeType _load(T&&);
700
701 template <typename T,
702 std::enable_if_t<is_std_vector_v<std::decay_t<T>>, void>* = nullptr
703 >
704 SizeType _load(T&&);
705
706 template <typename T,
707 std::enable_if_t<
708 is_std_deque_v<std::decay_t<T>> ||
709 is_std_list_v<std::decay_t<T>> ||
710 is_std_forward_list_v<std::decay_t<T>>,
711 void
712 >* = nullptr
713 >
714 SizeType _load(T&&);
715
716 template <typename T,
717 std::enable_if_t<is_std_map_v<std::decay_t<T>>, void>* = nullptr
718 >
719 SizeType _load(T&&);
720
721 template <typename T,
722 std::enable_if_t<is_std_unordered_map_v<std::decay_t<T>>, void>* = nullptr
723 >
724 SizeType _load(T&&);
725
726 template <typename T,
727 std::enable_if_t<is_std_set_v<std::decay_t<T>>, void>* = nullptr
728 >
729 SizeType _load(T&&);
730
731 template <typename T,
732 std::enable_if_t<is_std_unordered_set_v<std::decay_t<T>>, void>* = nullptr
733 >
734 SizeType _load(T&&);
735
736 template <typename T,
737 std::enable_if_t<std::is_enum_v<std::decay_t<T>>, void>* = nullptr
738 >
739 SizeType _load(T&&);
740
741 template <typename T,
742 std::enable_if_t<is_std_duration_v<std::decay_t<T>>, void>* = nullptr
743 >
744 SizeType _load(T&&);
745
746 template <typename T,
747 std::enable_if_t<is_std_time_point_v<std::decay_t<T>>, void>* = nullptr
748 >
749 SizeType _load(T&&);
750
751 template <typename T,
752 std::enable_if_t<is_std_optional_v<std::decay_t<T>>, void>* = nullptr
753 >
754 SizeType _load(T&&);
755
756 template <typename T,
757 std::enable_if_t<is_std_variant_v<std::decay_t<T>>, void>* = nullptr
758 >
759 SizeType _load(T&&);
760
761 template <typename T,
762 std::enable_if_t<is_std_tuple_v<std::decay_t<T>>, void>* = nullptr
763 >
764 SizeType _load(T&&);
765
766 template <typename T,
767 std::enable_if_t<is_std_array_v<std::decay_t<T>>, void>* = nullptr
768 >
769 SizeType _load(T&&);
770
771 template <typename T,
772 std::enable_if_t<!is_default_deserializable_v<std::decay_t<T>>, void>* = nullptr
773 >
774 SizeType _load(T&&);
775 };
776
777 // Constructor
778 template <typename Stream, typename SizeType>
Deserializer(Stream & stream)779 Deserializer<Stream, SizeType>::Deserializer(Stream& stream) : _stream(stream) {
780 }
781
782 // Operator ()
783 template <typename Stream, typename SizeType>
784 template <typename... T>
operator ()(T &&...items)785 SizeType Deserializer<Stream, SizeType>::operator() (T&&... items) {
786 return (_load(std::forward<T>(items)) + ...);
787 }
788
789 // Function: _variant_helper
790 template <typename Stream, typename SizeType>
791 template <size_t I, typename... ArgsT, std::enable_if_t<I==sizeof...(ArgsT)>*>
_variant_helper(size_t,std::variant<ArgsT...> &)792 SizeType Deserializer<Stream, SizeType>::_variant_helper(size_t, std::variant<ArgsT...>&) {
793 return 0;
794 }
795
796 // Function: _variant_helper
797 template <typename Stream, typename SizeType>
798 template <size_t I, typename... ArgsT, std::enable_if_t<I<sizeof...(ArgsT)>*>
_variant_helper(size_t i,std::variant<ArgsT...> & v)799 SizeType Deserializer<Stream, SizeType>::_variant_helper(size_t i, std::variant<ArgsT...>& v) {
800 if(i == 0) {
801 using type = ExtractType_t<I, std::variant<ArgsT...>>;
802 if(v.index() != I) {
803 static_assert(
804 std::is_default_constructible<type>::value,
805 "Failed to archive variant (type should be default constructible T())"
806 );
807 v = type();
808 }
809 return _load(std::get<type>(v));
810 }
811 return _variant_helper<I+1, ArgsT...>(i-1, v);
812 }
813
814 // arithmetic data type
815 template <typename Stream, typename SizeType>
816 template <typename T,
817 std::enable_if_t<std::is_arithmetic_v<std::decay_t<T>>, void>*
818 >
_load(T && t)819 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
820 _stream.read(reinterpret_cast<char*>(std::addressof(t)), sizeof(t));
821 return sizeof(t);
822 }
823
824 // std::basic_string
825 template <typename Stream, typename SizeType>
826 template <typename T,
827 std::enable_if_t<is_std_basic_string_v<std::decay_t<T>>, void>*
828 >
_load(T && t)829 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
830 using U = std::decay_t<T>;
831 typename U::size_type num_chars;
832 auto sz = _load(make_size_tag(num_chars));
833 t.resize(num_chars);
834 _stream.read(reinterpret_cast<char*>(t.data()), num_chars*sizeof(typename U::value_type));
835 return sz + num_chars*sizeof(typename U::value_type);
836 }
837
838 // std::vector
839 template <typename Stream, typename SizeType>
840 template <typename T,
841 std::enable_if_t<is_std_vector_v<std::decay_t<T>>, void>*
842 >
_load(T && t)843 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
844
845 using U = std::decay_t<T>;
846
847 typename U::size_type num_data;
848
849 auto sz = _load(make_size_tag(num_data));
850
851 if constexpr(std::is_arithmetic_v<typename U::value_type>) {
852 t.resize(num_data);
853 _stream.read(reinterpret_cast<char*>(t.data()), num_data * sizeof(typename U::value_type));
854 sz += num_data * sizeof(typename U::value_type);
855 }
856 else {
857 t.resize(num_data);
858 for(auto && v : t) {
859 sz += _load(v);
860 }
861 }
862 return sz;
863 }
864
865 // std::list and std::deque
866 template <typename Stream, typename SizeType>
867 template <typename T,
868 std::enable_if_t<is_std_deque_v<std::decay_t<T>> ||
869 is_std_list_v<std::decay_t<T>> ||
870 is_std_forward_list_v<std::decay_t<T>>, void>*
871 >
_load(T && t)872 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
873 using U = std::decay_t<T>;
874
875 typename U::size_type num_data;
876 auto sz = _load(make_size_tag(num_data));
877
878 t.resize(num_data);
879 for(auto && v : t) {
880 sz += _load(v);
881 }
882 return sz;
883 }
884
885 // std::map
886 template <typename Stream, typename SizeType>
887 template <typename T,
888 std::enable_if_t<is_std_map_v<std::decay_t<T>>, void>*
889 >
_load(T && t)890 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
891
892 using U = std::decay_t<T>;
893
894 typename U::size_type num_data;
895 auto sz = _load(make_size_tag(num_data));
896
897 t.clear();
898 auto hint = t.begin();
899
900 typename U::key_type k;
901 typename U::mapped_type v;
902
903 for(size_t i=0; i<num_data; ++i) {
904 sz += _load(make_kv_pair(k, v));
905 hint = t.emplace_hint(hint, std::move(k), std::move(v));
906 }
907 return sz;
908 }
909
910 // std::unordered_map
911 template <typename Stream, typename SizeType>
912 template <typename T,
913 std::enable_if_t<is_std_unordered_map_v<std::decay_t<T>>, void>*
914 >
_load(T && t)915 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
916 using U = std::decay_t<T>;
917 typename U::size_type num_data;
918 auto sz = _load(make_size_tag(num_data));
919
920 t.clear();
921 t.reserve(num_data);
922
923 typename U::key_type k;
924 typename U::mapped_type v;
925
926 for(size_t i=0; i<num_data; ++i) {
927 sz += _load(make_kv_pair(k, v));
928 t.emplace(std::move(k), std::move(v));
929 }
930
931 return sz;
932 }
933
934 // std::set
935 template <typename Stream, typename SizeType>
936 template <typename T,
937 std::enable_if_t<is_std_set_v<std::decay_t<T>>, void>*
938 >
_load(T && t)939 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
940
941 using U = std::decay_t<T>;
942
943 typename U::size_type num_data;
944 auto sz = _load(make_size_tag(num_data));
945
946 t.clear();
947 auto hint = t.begin();
948
949 typename U::key_type k;
950
951 for(size_t i=0; i<num_data; ++i) {
952 sz += _load(k);
953 hint = t.emplace_hint(hint, std::move(k));
954 }
955 return sz;
956 }
957
958 // std::unordered_set
959 template <typename Stream, typename SizeType>
960 template <typename T,
961 std::enable_if_t<is_std_unordered_set_v<std::decay_t<T>>, void>*
962 >
_load(T && t)963 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
964
965 using U = std::decay_t<T>;
966
967 typename U::size_type num_data;
968 auto sz = _load(make_size_tag(num_data));
969
970 t.clear();
971 t.reserve(num_data);
972
973 typename U::key_type k;
974
975 for(size_t i=0; i<num_data; ++i) {
976 sz += _load(k);
977 t.emplace(std::move(k));
978 }
979 return sz;
980 }
981
982 // enum data type
983 template <typename Stream, typename SizeType>
984 template <typename T,
985 std::enable_if_t<std::is_enum_v<std::decay_t<T>>, void>*
986 >
_load(T && t)987 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
988 using U = std::decay_t<T>;
989 std::underlying_type_t<U> k;
990 auto sz = _load(k);
991 t = static_cast<U>(k);
992 return sz;
993 }
994
995 // duration data type
996 template <typename Stream, typename SizeType>
997 template <typename T,
998 std::enable_if_t<is_std_duration_v<std::decay_t<T>>, void>*
999 >
_load(T && t)1000 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1001 using U = std::decay_t<T>;
1002 typename U::rep count;
1003 auto s = _load(count);
1004 t = U{count};
1005 return s;
1006 }
1007
1008 // time point data type
1009 template <typename Stream, typename SizeType>
1010 template <typename T,
1011 std::enable_if_t<is_std_time_point_v<std::decay_t<T>>, void>*
1012 >
_load(T && t)1013 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1014 using U = std::decay_t<T>;
1015 typename U::duration elapsed;
1016 auto s = _load(elapsed);
1017 t = U{elapsed};
1018 return s;
1019 }
1020
1021 // optional data type
1022 template <typename Stream, typename SizeType>
1023 template <typename T,
1024 std::enable_if_t<is_std_optional_v<std::decay_t<T>>, void>*
1025 >
_load(T && t)1026 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1027
1028 using U = std::decay_t<T>;
1029
1030 bool has_value;
1031 auto s = _load(has_value);
1032 if(has_value) {
1033 if(!t) {
1034 t = typename U::value_type();
1035 }
1036 s += _load(*t);
1037 }
1038 else {
1039 t.reset();
1040 }
1041 return s;
1042 }
1043
1044 // variant type
1045 template <typename Stream, typename SizeType>
1046 template <typename T,
1047 std::enable_if_t<is_std_variant_v<std::decay_t<T>>, void>*
1048 >
_load(T && t)1049 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1050 std::decay_t<decltype(t.index())> idx;
1051 auto s = _load(idx);
1052 return s + _variant_helper(idx, t);
1053 }
1054
1055 // tuple type
1056 template <typename Stream, typename SizeType>
1057 template <typename T,
1058 std::enable_if_t<is_std_tuple_v<std::decay_t<T>>, void>*
1059 >
_load(T && t)1060 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1061 return std::apply(
1062 [&] (auto&&... args) {
1063 return (_load(std::forward<decltype(args)>(args)) + ... + 0);
1064 },
1065 std::forward<T>(t)
1066 );
1067 }
1068
1069 // array
1070 template <typename Stream, typename SizeType>
1071 template <typename T,
1072 std::enable_if_t<is_std_array_v<std::decay_t<T>>, void>*
1073 >
_load(T && t)1074 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1075
1076 using U = std::decay_t<T>;
1077
1078 static_assert(std::tuple_size<U>::value > 0, "Array size can't be zero");
1079
1080 SizeType sz;
1081
1082 if constexpr(std::is_arithmetic_v<typename U::value_type>) {
1083 _stream.read(reinterpret_cast<char*>(t.data()), sizeof(t));
1084 sz = sizeof(t);
1085 }
1086 else {
1087 sz = 0;
1088 for(auto && v : t) {
1089 sz += _load(v);
1090 }
1091 }
1092
1093 return sz;
1094 }
1095
1096 // custom save method
1097 template <typename Stream, typename SizeType>
1098 template <typename T,
1099 std::enable_if_t<!is_default_deserializable_v<std::decay_t<T>>, void>*
1100 >
_load(T && t)1101 SizeType Deserializer<Stream, SizeType>::_load(T&& t) {
1102 return t.load(*this);
1103 }
1104
1105 } // ned of namespace tf -----------------------------------------------------
1106
1107
1108
1109
1110
1111
1112