ysaveload.h 22 KB

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