ysaveload.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. #pragma once
  2. #include <util/generic/fwd.h>
  3. #include <util/generic/strbuf.h>
  4. #include <util/generic/string.h>
  5. #include <util/generic/yexception.h>
  6. #include <util/generic/typetraits.h>
  7. #include <util/generic/algorithm.h>
  8. #include <util/stream/output.h>
  9. #include <util/stream/input.h>
  10. #ifndef __NVCC__
  11. // cuda is compiled in C++14 mode at the time
  12. #include <variant>
  13. #endif
  14. template <typename T>
  15. class TSerializeTypeTraits {
  16. public:
  17. /*
  18. * pointer types cannot be serialized as POD-type
  19. */
  20. enum {
  21. IsSerializablePod = TTypeTraits<T>::IsPod && !std::is_pointer<T>::value
  22. };
  23. };
  24. struct TSerializeException: public yexception {
  25. };
  26. struct TLoadEOF: public TSerializeException {
  27. };
  28. template <class T>
  29. static inline void Save(IOutputStream* out, const T& t);
  30. template <class T>
  31. static inline void SaveArray(IOutputStream* out, const T* t, size_t len);
  32. template <class T>
  33. static inline void Load(IInputStream* in, T& t);
  34. template <class T>
  35. static inline void LoadArray(IInputStream* in, T* t, size_t len);
  36. template <class T, class TStorage>
  37. static inline void Load(IInputStream* in, T& t, TStorage& pool);
  38. template <class T, class TStorage>
  39. static inline void LoadArray(IInputStream* in, T* t, size_t len, TStorage& pool);
  40. template <class T>
  41. static inline void SavePodType(IOutputStream* rh, const T& t) {
  42. rh->Write(&t, sizeof(T));
  43. }
  44. namespace NPrivate {
  45. [[noreturn]] void ThrowLoadEOFException(size_t typeSize, size_t realSize, TStringBuf structName);
  46. [[noreturn]] void ThrowUnexpectedVariantTagException(ui8 tagIndex);
  47. }
  48. template <class T>
  49. static inline void LoadPodType(IInputStream* rh, T& t) {
  50. const size_t res = rh->Load(&t, sizeof(T));
  51. if (Y_UNLIKELY(res != sizeof(T))) {
  52. ::NPrivate::ThrowLoadEOFException(sizeof(T), res, TStringBuf("pod type"));
  53. }
  54. }
  55. template <class T>
  56. static inline void SavePodArray(IOutputStream* rh, const T* arr, size_t count) {
  57. rh->Write(arr, sizeof(T) * count);
  58. }
  59. template <class T>
  60. static inline void LoadPodArray(IInputStream* rh, T* arr, size_t count) {
  61. const size_t len = sizeof(T) * count;
  62. const size_t res = rh->Load(arr, len);
  63. if (Y_UNLIKELY(res != len)) {
  64. ::NPrivate::ThrowLoadEOFException(len, res, TStringBuf("pod array"));
  65. }
  66. }
  67. template <class It>
  68. static inline void SaveIterRange(IOutputStream* rh, It b, It e) {
  69. while (b != e) {
  70. ::Save(rh, *b++);
  71. }
  72. }
  73. template <class It>
  74. static inline void LoadIterRange(IInputStream* rh, It b, It e) {
  75. while (b != e) {
  76. ::Load(rh, *b++);
  77. }
  78. }
  79. template <class It, class TStorage>
  80. static inline void LoadIterRange(IInputStream* rh, It b, It e, TStorage& pool) {
  81. while (b != e) {
  82. ::Load(rh, *b++, pool);
  83. }
  84. }
  85. template <class T, bool isPod>
  86. struct TSerializerTakingIntoAccountThePodType {
  87. static inline void Save(IOutputStream* out, const T& t) {
  88. ::SavePodType(out, t);
  89. }
  90. static inline void Load(IInputStream* in, T& t) {
  91. ::LoadPodType(in, t);
  92. }
  93. template <class TStorage>
  94. static inline void Load(IInputStream* in, T& t, TStorage& /*pool*/) {
  95. ::LoadPodType(in, t);
  96. }
  97. static inline void SaveArray(IOutputStream* out, const T* t, size_t len) {
  98. ::SavePodArray(out, t, len);
  99. }
  100. static inline void LoadArray(IInputStream* in, T* t, size_t len) {
  101. ::LoadPodArray(in, t, len);
  102. }
  103. };
  104. namespace NHasSaveLoad {
  105. Y_HAS_MEMBER(SaveLoad);
  106. }
  107. template <class T, class = void>
  108. struct TSerializerMethodSelector;
  109. template <class T>
  110. struct TSerializerMethodSelector<T, std::enable_if_t<NHasSaveLoad::THasSaveLoad<T>::value>> {
  111. static inline void Save(IOutputStream* out, const T& t) {
  112. //assume Save clause do not change t
  113. (const_cast<T&>(t)).SaveLoad(out);
  114. }
  115. static inline void Load(IInputStream* in, T& t) {
  116. t.SaveLoad(in);
  117. }
  118. template <class TStorage>
  119. static inline void Load(IInputStream* in, T& t, TStorage& pool) {
  120. t.SaveLoad(in, pool);
  121. }
  122. };
  123. template <class T>
  124. struct TSerializerMethodSelector<T, std::enable_if_t<!NHasSaveLoad::THasSaveLoad<T>::value>> {
  125. static inline void Save(IOutputStream* out, const T& t) {
  126. t.Save(out);
  127. }
  128. static inline void Load(IInputStream* in, T& t) {
  129. t.Load(in);
  130. }
  131. template <class TStorage>
  132. static inline void Load(IInputStream* in, T& t, TStorage& pool) {
  133. t.Load(in, pool);
  134. }
  135. };
  136. template <class T>
  137. struct TSerializerTakingIntoAccountThePodType<T, false>: public TSerializerMethodSelector<T> {
  138. static inline void SaveArray(IOutputStream* out, const T* t, size_t len) {
  139. ::SaveIterRange(out, t, t + len);
  140. }
  141. static inline void LoadArray(IInputStream* in, T* t, size_t len) {
  142. ::LoadIterRange(in, t, t + len);
  143. }
  144. template <class TStorage>
  145. static inline void LoadArray(IInputStream* in, T* t, size_t len, TStorage& pool) {
  146. ::LoadIterRange(in, t, t + len, pool);
  147. }
  148. };
  149. template <class It, bool isPtr>
  150. struct TRangeSerialize {
  151. static inline void Save(IOutputStream* rh, It b, It e) {
  152. SaveArray(rh, b, e - b);
  153. }
  154. static inline void Load(IInputStream* rh, It b, It e) {
  155. LoadArray(rh, b, e - b);
  156. }
  157. template <class TStorage>
  158. static inline void Load(IInputStream* rh, It b, It e, TStorage& pool) {
  159. LoadArray(rh, b, e - b, pool);
  160. }
  161. };
  162. template <class It>
  163. struct TRangeSerialize<It, false> {
  164. static inline void Save(IOutputStream* rh, It b, It e) {
  165. SaveIterRange(rh, b, e);
  166. }
  167. static inline void Load(IInputStream* rh, It b, It e) {
  168. LoadIterRange(rh, b, e);
  169. }
  170. template <class TStorage>
  171. static inline void Load(IInputStream* rh, It b, It e, TStorage& pool) {
  172. LoadIterRange(rh, b, e, pool);
  173. }
  174. };
  175. template <class It>
  176. static inline void SaveRange(IOutputStream* rh, It b, It e) {
  177. TRangeSerialize<It, std::is_pointer<It>::value>::Save(rh, b, e);
  178. }
  179. template <class It>
  180. static inline void LoadRange(IInputStream* rh, It b, It e) {
  181. TRangeSerialize<It, std::is_pointer<It>::value>::Load(rh, b, e);
  182. }
  183. template <class It, class TStorage>
  184. static inline void LoadRange(IInputStream* rh, It b, It e, TStorage& pool) {
  185. TRangeSerialize<It, std::is_pointer<It>::value>::Load(rh, b, e, pool);
  186. }
  187. template <class T>
  188. class TSerializer: public TSerializerTakingIntoAccountThePodType<T, TSerializeTypeTraits<T>::IsSerializablePod> {
  189. };
  190. template <class T>
  191. class TArraySerializer: public TSerializerTakingIntoAccountThePodType<T, TSerializeTypeTraits<T>::IsSerializablePod> {
  192. };
  193. template <class T>
  194. static inline void Save(IOutputStream* out, const T& t) {
  195. TSerializer<T>::Save(out, t);
  196. }
  197. template <class T>
  198. static inline void SaveArray(IOutputStream* out, const T* t, size_t len) {
  199. TArraySerializer<T>::SaveArray(out, t, len);
  200. }
  201. template <class T>
  202. static inline void Load(IInputStream* in, T& t) {
  203. TSerializer<T>::Load(in, t);
  204. }
  205. template <class T>
  206. static inline void LoadArray(IInputStream* in, T* t, size_t len) {
  207. TArraySerializer<T>::LoadArray(in, t, len);
  208. }
  209. template <class T, class TStorage>
  210. static inline void Load(IInputStream* in, T& t, TStorage& pool) {
  211. TSerializer<T>::Load(in, t, pool);
  212. }
  213. template <class T, class TStorage>
  214. static inline void LoadArray(IInputStream* in, T* t, size_t len, TStorage& pool) {
  215. TArraySerializer<T>::LoadArray(in, t, len, pool);
  216. }
  217. static inline void SaveSize(IOutputStream* rh, size_t len) {
  218. if ((ui64)len < 0xffffffff) {
  219. ::Save(rh, (ui32)len);
  220. } else {
  221. ::Save(rh, (ui32)0xffffffff);
  222. ::Save(rh, (ui64)len);
  223. }
  224. }
  225. static inline size_t LoadSize(IInputStream* rh) {
  226. ui32 oldVerSize;
  227. ui64 newVerSize;
  228. ::Load(rh, oldVerSize);
  229. if (oldVerSize != 0xffffffff) {
  230. return oldVerSize;
  231. } else {
  232. ::Load(rh, newVerSize);
  233. return newVerSize;
  234. }
  235. }
  236. template <class C>
  237. static inline void LoadSizeAndResize(IInputStream* rh, C& c) {
  238. c.resize(LoadSize(rh));
  239. }
  240. template <class TStorage>
  241. static inline char* AllocateFromPool(TStorage& pool, size_t len) {
  242. return static_cast<char*>(pool.Allocate(len));
  243. }
  244. template <>
  245. class TSerializer<const char*> {
  246. public:
  247. static inline void Save(IOutputStream* rh, const char* s) {
  248. size_t length = strlen(s);
  249. ::SaveSize(rh, length);
  250. ::SavePodArray(rh, s, length);
  251. }
  252. template <class Char, class TStorage>
  253. static inline void Load(IInputStream* rh, Char*& s, TStorage& pool) {
  254. const size_t len = LoadSize(rh);
  255. char* res = AllocateFromPool(pool, len + 1);
  256. ::LoadPodArray(rh, res, len);
  257. res[len] = 0;
  258. s = res;
  259. }
  260. };
  261. template <class TVec>
  262. class TVectorSerializer {
  263. using TIter = typename TVec::iterator;
  264. public:
  265. static inline void Save(IOutputStream* rh, const TVec& v) {
  266. ::SaveSize(rh, v.size());
  267. ::SaveRange(rh, v.begin(), v.end());
  268. }
  269. static inline void Load(IInputStream* rh, TVec& v) {
  270. ::LoadSizeAndResize(rh, v);
  271. TIter b = v.begin();
  272. TIter e = (TIter)v.end();
  273. ::LoadRange(rh, b, e);
  274. }
  275. template <class TStorage>
  276. static inline void Load(IInputStream* rh, TVec& v, TStorage& pool) {
  277. ::LoadSizeAndResize(rh, v);
  278. TIter b = v.begin();
  279. TIter e = (TIter)v.end();
  280. ::LoadRange(rh, b, e, pool);
  281. }
  282. };
  283. template <class T, class A>
  284. class TSerializer<TVector<T, A>>: public TVectorSerializer<TVector<T, A>> {
  285. };
  286. template <class T, class A>
  287. class TSerializer<std::vector<T, A>>: public TVectorSerializer<std::vector<T, A>> {
  288. };
  289. template <class T, class A>
  290. class TSerializer<TList<T, A>>: public TVectorSerializer<TList<T, A>> {
  291. };
  292. template <class T, class A>
  293. class TSerializer<std::list<T, A>>: public TVectorSerializer<std::list<T, A>> {
  294. };
  295. template <>
  296. class TSerializer<TString>: public TVectorSerializer<TString> {
  297. };
  298. template <>
  299. class TSerializer<TUtf16String>: public TVectorSerializer<TUtf16String> {
  300. };
  301. template <class TChar>
  302. class TSerializer<std::basic_string<TChar>>: public TVectorSerializer<std::basic_string<TChar>> {
  303. };
  304. template <class T, class A>
  305. class TSerializer<TDeque<T, A>>: public TVectorSerializer<TDeque<T, A>> {
  306. };
  307. template <class T, class A>
  308. class TSerializer<std::deque<T, A>>: public TVectorSerializer<std::deque<T, A>> {
  309. };
  310. template <class TArray>
  311. class TStdArraySerializer {
  312. public:
  313. static inline void Save(IOutputStream* rh, const TArray& a) {
  314. ::SaveArray(rh, a.data(), a.size());
  315. }
  316. static inline void Load(IInputStream* rh, TArray& a) {
  317. ::LoadArray(rh, a.data(), a.size());
  318. }
  319. };
  320. template <class T, size_t N>
  321. class TSerializer<std::array<T, N>>: public TStdArraySerializer<std::array<T, N>> {
  322. };
  323. template <class A, class B>
  324. class TSerializer<std::pair<A, B>> {
  325. using TPair = std::pair<A, B>;
  326. public:
  327. static inline void Save(IOutputStream* rh, const TPair& p) {
  328. ::Save(rh, p.first);
  329. ::Save(rh, p.second);
  330. }
  331. static inline void Load(IInputStream* rh, TPair& p) {
  332. ::Load(rh, p.first);
  333. ::Load(rh, p.second);
  334. }
  335. template <class TStorage>
  336. static inline void Load(IInputStream* rh, TPair& p, TStorage& pool) {
  337. ::Load(rh, p.first, pool);
  338. ::Load(rh, p.second, pool);
  339. }
  340. };
  341. template <class T>
  342. struct TTupleSerializer {
  343. template <class F, class Tuple, size_t... Indices>
  344. static inline void ReverseUseless(F&& f, Tuple&& t, std::index_sequence<Indices...>) {
  345. ApplyToMany(
  346. std::forward<F>(f),
  347. // We need to do this trick because we don't want to break backward compatibility.
  348. // Tuples are being packed in reverse order.
  349. std::get<std::tuple_size<T>::value - Indices - 1>(std::forward<Tuple>(t))...);
  350. }
  351. static inline void Save(IOutputStream* stream, const T& t) {
  352. ReverseUseless([&](const auto& v) { ::Save(stream, v); }, t,
  353. std::make_index_sequence<std::tuple_size<T>::value>{});
  354. }
  355. static inline void Load(IInputStream* stream, T& t) {
  356. ReverseUseless([&](auto& v) { ::Load(stream, v); }, t,
  357. std::make_index_sequence<std::tuple_size<T>::value>{});
  358. }
  359. };
  360. template <typename... TArgs>
  361. struct TSerializer<std::tuple<TArgs...>>: TTupleSerializer<std::tuple<TArgs...>> {
  362. };
  363. template <>
  364. class TSerializer<TBuffer> {
  365. public:
  366. static void Save(IOutputStream* rh, const TBuffer& buf);
  367. static void Load(IInputStream* rh, TBuffer& buf);
  368. };
  369. template <class TSetOrMap, class TValue>
  370. class TSetSerializerInserterBase {
  371. public:
  372. inline TSetSerializerInserterBase(TSetOrMap& s)
  373. : S_(s)
  374. {
  375. S_.clear();
  376. }
  377. inline void Insert(const TValue& v) {
  378. S_.insert(v);
  379. }
  380. protected:
  381. TSetOrMap& S_;
  382. };
  383. template <class TSetOrMap, class TValue, bool sorted>
  384. class TSetSerializerInserter: public TSetSerializerInserterBase<TSetOrMap, TValue> {
  385. using TBase = TSetSerializerInserterBase<TSetOrMap, TValue>;
  386. public:
  387. inline TSetSerializerInserter(TSetOrMap& s, size_t cnt)
  388. : TBase(s)
  389. {
  390. Y_UNUSED(cnt);
  391. }
  392. };
  393. template <class TSetType, class TValue>
  394. class TSetSerializerInserter<TSetType, TValue, true>: public TSetSerializerInserterBase<TSetType, TValue> {
  395. using TBase = TSetSerializerInserterBase<TSetType, TValue>;
  396. public:
  397. inline TSetSerializerInserter(TSetType& s, size_t cnt)
  398. : TBase(s)
  399. {
  400. Y_UNUSED(cnt);
  401. P_ = this->S_.begin();
  402. }
  403. inline void Insert(const TValue& v) {
  404. P_ = this->S_.insert(P_, v);
  405. }
  406. private:
  407. typename TSetType::iterator P_;
  408. };
  409. template <class T1, class T2, class T3, class T4, class T5, class TValue>
  410. class TSetSerializerInserter<THashMap<T1, T2, T3, T4, T5>, TValue, false>: public TSetSerializerInserterBase<THashMap<T1, T2, T3, T4, T5>, TValue> {
  411. using TMapType = THashMap<T1, T2, T3, T4, T5>;
  412. using TBase = TSetSerializerInserterBase<TMapType, TValue>;
  413. public:
  414. inline TSetSerializerInserter(TMapType& m, size_t cnt)
  415. : TBase(m)
  416. {
  417. m.reserve(cnt);
  418. }
  419. };
  420. template <class T1, class T2, class T3, class T4, class T5, class TValue>
  421. class TSetSerializerInserter<THashMultiMap<T1, T2, T3, T4, T5>, TValue, false>: public TSetSerializerInserterBase<THashMultiMap<T1, T2, T3, T4, T5>, TValue> {
  422. using TMapType = THashMultiMap<T1, T2, T3, T4, T5>;
  423. using TBase = TSetSerializerInserterBase<TMapType, TValue>;
  424. public:
  425. inline TSetSerializerInserter(TMapType& m, size_t cnt)
  426. : TBase(m)
  427. {
  428. m.reserve(cnt);
  429. }
  430. };
  431. template <class T1, class T2, class T3, class T4, class TValue>
  432. class TSetSerializerInserter<THashSet<T1, T2, T3, T4>, TValue, false>: public TSetSerializerInserterBase<THashSet<T1, T2, T3, T4>, TValue> {
  433. using TSetType = THashSet<T1, T2, T3, T4>;
  434. using TBase = TSetSerializerInserterBase<TSetType, TValue>;
  435. public:
  436. inline TSetSerializerInserter(TSetType& s, size_t cnt)
  437. : TBase(s)
  438. {
  439. s.reserve(cnt);
  440. }
  441. };
  442. template <class TSetType, class TValue, bool sorted>
  443. class TSetSerializerBase {
  444. public:
  445. static inline void Save(IOutputStream* rh, const TSetType& s) {
  446. ::SaveSize(rh, s.size());
  447. ::SaveRange(rh, s.begin(), s.end());
  448. }
  449. static inline void Load(IInputStream* rh, TSetType& s) {
  450. const size_t cnt = ::LoadSize(rh);
  451. TSetSerializerInserter<TSetType, TValue, sorted> ins(s, cnt);
  452. TValue v;
  453. for (size_t i = 0; i != cnt; ++i) {
  454. ::Load(rh, v);
  455. ins.Insert(v);
  456. }
  457. }
  458. template <class TStorage>
  459. static inline void Load(IInputStream* rh, TSetType& s, TStorage& pool) {
  460. const size_t cnt = ::LoadSize(rh);
  461. TSetSerializerInserter<TSetType, TValue, sorted> ins(s, cnt);
  462. TValue v;
  463. for (size_t i = 0; i != cnt; ++i) {
  464. ::Load(rh, v, pool);
  465. ins.Insert(v);
  466. }
  467. }
  468. };
  469. template <class TMapType, bool sorted = false>
  470. struct TMapSerializer: public TSetSerializerBase<TMapType, std::pair<typename TMapType::key_type, typename TMapType::mapped_type>, sorted> {
  471. };
  472. template <class TSetType, bool sorted = false>
  473. struct TSetSerializer: public TSetSerializerBase<TSetType, typename TSetType::value_type, sorted> {
  474. };
  475. template <class T1, class T2, class T3, class T4>
  476. class TSerializer<TMap<T1, T2, T3, T4>>: public TMapSerializer<TMap<T1, T2, T3, T4>, true> {
  477. };
  478. template <class K, class T, class C, class A>
  479. class TSerializer<std::map<K, T, C, A>>: public TMapSerializer<std::map<K, T, C, A>, true> {
  480. };
  481. template <class T1, class T2, class T3, class T4>
  482. class TSerializer<TMultiMap<T1, T2, T3, T4>>: public TMapSerializer<TMultiMap<T1, T2, T3, T4>, true> {
  483. };
  484. template <class K, class T, class C, class A>
  485. class TSerializer<std::multimap<K, T, C, A>>: public TMapSerializer<std::multimap<K, T, C, A>, true> {
  486. };
  487. template <class T1, class T2, class T3, class T4, class T5>
  488. class TSerializer<THashMap<T1, T2, T3, T4, T5>>: public TMapSerializer<THashMap<T1, T2, T3, T4, T5>, false> {
  489. };
  490. template <class T1, class T2, class T3, class T4, class T5>
  491. class TSerializer<THashMultiMap<T1, T2, T3, T4, T5>>: public TMapSerializer<THashMultiMap<T1, T2, T3, T4, T5>, false> {
  492. };
  493. template <class K, class C, class A>
  494. class TSerializer<TSet<K, C, A>>: public TSetSerializer<TSet<K, C, A>, true> {
  495. };
  496. template <class K, class C, class A>
  497. class TSerializer<std::set<K, C, A>>: public TSetSerializer<std::set<K, C, A>, true> {
  498. };
  499. template <class T1, class T2, class T3, class T4>
  500. class TSerializer<THashSet<T1, T2, T3, T4>>: public TSetSerializer<THashSet<T1, T2, T3, T4>, false> {
  501. };
  502. template <class T1, class T2>
  503. class TSerializer<TQueue<T1, T2>> {
  504. public:
  505. static inline void Save(IOutputStream* rh, const TQueue<T1, T2>& v) {
  506. ::Save(rh, v.Container());
  507. }
  508. static inline void Load(IInputStream* in, TQueue<T1, T2>& t) {
  509. ::Load(in, t.Container());
  510. }
  511. };
  512. template <class T1, class T2, class T3>
  513. class TSerializer<TPriorityQueue<T1, T2, T3>> {
  514. public:
  515. static inline void Save(IOutputStream* rh, const TPriorityQueue<T1, T2, T3>& v) {
  516. ::Save(rh, v.Container());
  517. }
  518. static inline void Load(IInputStream* in, TPriorityQueue<T1, T2, T3>& t) {
  519. ::Load(in, t.Container());
  520. }
  521. };
  522. #ifndef __NVCC__
  523. namespace NPrivate {
  524. template <class Variant, class T, size_t I>
  525. void LoadVariantAlternative(IInputStream* is, Variant& v) {
  526. T loaded;
  527. ::Load(is, loaded);
  528. v.template emplace<I>(std::move(loaded));
  529. }
  530. }
  531. template <typename... Args>
  532. struct TSerializer<std::variant<Args...>> {
  533. using TVar = std::variant<Args...>;
  534. static_assert(sizeof...(Args) < 256, "We use ui8 to store tag");
  535. static void Save(IOutputStream* os, const TVar& v) {
  536. ::Save<ui8>(os, v.index());
  537. std::visit([os](const auto& data) {
  538. ::Save(os, data);
  539. }, v);
  540. }
  541. static void Load(IInputStream* is, TVar& v) {
  542. ui8 index;
  543. ::Load(is, index);
  544. if (Y_UNLIKELY(index >= sizeof...(Args))) {
  545. ::NPrivate::ThrowUnexpectedVariantTagException(index);
  546. }
  547. LoadImpl(is, v, index, std::index_sequence_for<Args...>{});
  548. }
  549. private:
  550. template <size_t... Is>
  551. static void LoadImpl(IInputStream* is, TVar& v, ui8 index, std::index_sequence<Is...>) {
  552. using TLoader = void (*)(IInputStream*, TVar & v);
  553. constexpr TLoader loaders[] = {::NPrivate::LoadVariantAlternative<TVar, Args, Is>...};
  554. loaders[index](is, v);
  555. }
  556. };
  557. #endif
  558. template <class T>
  559. static inline void SaveLoad(IOutputStream* out, const T& t) {
  560. Save(out, t);
  561. }
  562. template <class T>
  563. static inline void SaveLoad(IInputStream* in, T& t) {
  564. Load(in, t);
  565. }
  566. template <class S, class... Ts>
  567. static inline void SaveMany(S* s, const Ts&... t) {
  568. ApplyToMany([&](const auto& v) { Save(s, v); }, t...);
  569. }
  570. template <class S, class... Ts>
  571. static inline void LoadMany(S* s, Ts&... t) {
  572. ApplyToMany([&](auto& v) { Load(s, v); }, t...);
  573. }
  574. #define Y_SAVELOAD_DEFINE(...) \
  575. inline void Save(IOutputStream* s) const { \
  576. ::SaveMany(s, __VA_ARGS__); \
  577. } \
  578. \
  579. inline void Load(IInputStream* s) { \
  580. ::LoadMany(s, __VA_ARGS__); \
  581. }
  582. #define Y_SAVELOAD_DEFINE_OVERRIDE(...) \
  583. void Save(IOutputStream* s) const override { \
  584. ::SaveMany(s, __VA_ARGS__); \
  585. } \
  586. \
  587. void Load(IInputStream* s) override { \
  588. ::LoadMany(s, __VA_ARGS__); \
  589. }
  590. template <class T>
  591. struct TNonVirtualSaver {
  592. const T* Data;
  593. void Save(IOutputStream* out) const {
  594. Data->T::Save(out);
  595. }
  596. };
  597. template <typename S, typename T, typename... R>
  598. inline void LoadMany(S* s, TNonVirtualSaver<T> t, R&... r) {
  599. const_cast<T*>(t.Data)->T::Load(s);
  600. ::LoadMany(s, r...);
  601. }