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