ysaveload.h 22 KB

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