Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
serialize.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 The Bitcoin Core developers
3// Distributed under the MIT software license, see the accompanying
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6#ifndef BITCOIN_SERIALIZE_H
7#define BITCOIN_SERIALIZE_H
8
9#include <compat/endian.h>
10#include <prevector.h>
11#include <rcu.h>
12#include <span.h>
13
14#include <algorithm>
15#include <array>
16#include <cstdint>
17#include <cstring>
18#include <ios>
19#include <limits>
20#include <map>
21#include <memory>
22#include <set>
23#include <string>
24#include <utility>
25#include <vector>
26
31static constexpr uint64_t MAX_SIZE = 0x02000000;
32
37static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
38
51
55template <typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) {
56 s.write(AsBytes(Span{&obj, 1}));
57}
58template <typename Stream>
60 obj = htole16(obj);
61 s.write(AsBytes(Span{&obj, 1}));
62}
63template <typename Stream>
65 obj = htobe16(obj);
66 s.write(AsBytes(Span{&obj, 1}));
67}
68template <typename Stream>
70 obj = htole32(obj);
71 s.write(AsBytes(Span{&obj, 1}));
72}
73template <typename Stream>
75 obj = htobe32(obj);
76 s.write(AsBytes(Span{&obj, 1}));
77}
78template <typename Stream>
80 obj = htole64(obj);
81 s.write(AsBytes(Span{&obj, 1}));
82}
83template <typename Stream> inline uint8_t ser_readdata8(Stream &s) {
85 s.read(AsWritableBytes(Span{&obj, 1}));
86 return obj;
87}
88template <typename Stream> inline uint16_t ser_readdata16(Stream &s) {
90 s.read(AsWritableBytes(Span{&obj, 1}));
91 return le16toh(obj);
92}
93template <typename Stream> inline uint16_t ser_readdata16be(Stream &s) {
95 s.read(AsWritableBytes(Span{&obj, 1}));
96 return be16toh(obj);
97}
98template <typename Stream> inline uint32_t ser_readdata32(Stream &s) {
100 s.read(AsWritableBytes(Span{&obj, 1}));
101 return le32toh(obj);
102}
103template <typename Stream> inline uint32_t ser_readdata32be(Stream &s) {
105 s.read(AsWritableBytes(Span{&obj, 1}));
106 return be32toh(obj);
107}
108template <typename Stream> inline uint64_t ser_readdata64(Stream &s) {
110 s.read(AsWritableBytes(Span{&obj, 1}));
111 return le64toh(obj);
112}
114 uint64_t tmp;
115 std::memcpy(&tmp, &x, sizeof(x));
116 static_assert(sizeof(tmp) == sizeof(x),
117 "double and uint64_t assumed to have the same size");
118 return tmp;
119}
121 uint32_t tmp;
122 std::memcpy(&tmp, &x, sizeof(x));
123 static_assert(sizeof(tmp) == sizeof(x),
124 "float and uint32_t assumed to have the same size");
125 return tmp;
126}
128 double tmp;
129 std::memcpy(&tmp, &y, sizeof(y));
130 static_assert(sizeof(tmp) == sizeof(y),
131 "double and uint64_t assumed to have the same size");
132 return tmp;
133}
135 float tmp;
136 std::memcpy(&tmp, &y, sizeof(y));
137 static_assert(sizeof(tmp) == sizeof(y),
138 "float and uint32_t assumed to have the same size");
139 return tmp;
140}
141
143//
144// Templates for serializing to anything that looks like a stream,
145// i.e. anything that supports .read(Span<std::byte>) and .write(Span<const
146// std::byte>)
147//
148class CSizeComputer;
149
150enum {
151 // primary actions
152 SER_NETWORK = (1 << 0),
153 SER_DISK = (1 << 1),
154 SER_GETHASH = (1 << 2),
155};
156
159template <typename X> X &ReadWriteAsHelper(X &x) {
160 return x;
161}
162template <typename X> const X &ReadWriteAsHelper(const X &x) {
163 return x;
164}
165
166#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
167#define READWRITEAS(type, obj) \
168 (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
169#define SER_READ(obj, code) \
170 ::SerRead( \
171 s, ser_action, obj, \
172 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
173#define SER_WRITE(obj, code) \
174 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
175
194#define FORMATTER_METHODS(cls, obj) \
195 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
196 SerializationOps(obj, s, CSerActionSerialize()); \
197 } \
198 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
199 SerializationOps(obj, s, CSerActionUnserialize()); \
200 } \
201 template <typename Stream, typename Type, typename Operation> \
202 static inline void SerializationOps(Type &obj, Stream &s, \
203 Operation ser_action)
204
213#define SERIALIZE_METHODS(cls, obj) \
214 template <typename Stream> void Serialize(Stream &s) const { \
215 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
216 "Serialize type mismatch"); \
217 Ser(s, *this); \
218 } \
219 template <typename Stream> void Unserialize(Stream &s) { \
220 static_assert(std::is_same<cls &, decltype(*this)>::value, \
221 "Unserialize type mismatch"); \
222 Unser(s, *this); \
223 } \
224 FORMATTER_METHODS(cls, obj)
225
226#ifndef CHAR_EQUALS_INT8
227// char serialization forbidden. Use uint8_t or int8_t
228template <typename Stream> void Serialize(Stream &, char) = delete;
229#endif
230template <typename Stream> inline void Serialize(Stream &s, int8_t a) {
231 ser_writedata8(s, a);
232}
233template <typename Stream> inline void Serialize(Stream &s, uint8_t a) {
234 ser_writedata8(s, a);
235}
236template <typename Stream> inline void Serialize(Stream &s, int16_t a) {
237 ser_writedata16(s, a);
238}
239template <typename Stream> inline void Serialize(Stream &s, uint16_t a) {
240 ser_writedata16(s, a);
241}
242template <typename Stream> inline void Serialize(Stream &s, int32_t a) {
243 ser_writedata32(s, a);
244}
245template <typename Stream> inline void Serialize(Stream &s, uint32_t a) {
246 ser_writedata32(s, a);
247}
248template <typename Stream> inline void Serialize(Stream &s, int64_t a) {
249 ser_writedata64(s, a);
250}
251template <typename Stream> inline void Serialize(Stream &s, uint64_t a) {
252 ser_writedata64(s, a);
253}
254template <typename Stream> inline void Serialize(Stream &s, float a) {
256}
257template <typename Stream> inline void Serialize(Stream &s, double a) {
259}
260template <typename Stream, size_t N>
261inline void Serialize(Stream &s, const int8_t (&a)[N]) {
262 s.write(a, N);
263}
264template <typename Stream, size_t N>
265inline void Serialize(Stream &s, const uint8_t (&a)[N]) {
266 s.write(MakeByteSpan(a));
267}
268template <typename Stream, size_t N>
269inline void Serialize(Stream &s, const std::array<int8_t, N> &a) {
270 s.write(a.data(), N);
271}
272template <typename Stream, size_t N>
273inline void Serialize(Stream &s, const std::array<uint8_t, N> &a) {
274 s.write(MakeByteSpan(a));
275}
276#ifndef CHAR_EQUALS_INT8
277// char serialization forbidden. Use uint8_t or int8_t
278template <typename Stream> void Unserialize(Stream &, char) = delete;
279template <typename Stream, size_t N>
280inline void Serialize(Stream &s, const char (&a)[N]) {
281 s.write(MakeByteSpan(a));
282}
283template <typename Stream, size_t N>
284inline void Serialize(Stream &s, const std::array<char, N> &a) {
285 s.write(MakeByteSpan(a));
286}
287#endif
288template <typename Stream>
289inline void Serialize(Stream &s, const Span<const uint8_t> &span) {
290 s.write(AsBytes(span));
291}
292template <typename Stream>
293inline void Serialize(Stream &s, const Span<uint8_t> &span) {
294 s.write(AsBytes(span));
295}
296template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) {
297 a = ser_readdata8(s);
298}
299template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) {
300 a = ser_readdata8(s);
301}
302template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) {
303 a = ser_readdata16(s);
304}
305template <typename Stream> inline void Unserialize(Stream &s, uint16_t &a) {
306 a = ser_readdata16(s);
307}
308template <typename Stream> inline void Unserialize(Stream &s, int32_t &a) {
309 a = ser_readdata32(s);
310}
311template <typename Stream> inline void Unserialize(Stream &s, uint32_t &a) {
312 a = ser_readdata32(s);
313}
314template <typename Stream> inline void Unserialize(Stream &s, int64_t &a) {
315 a = ser_readdata64(s);
316}
317template <typename Stream> inline void Unserialize(Stream &s, uint64_t &a) {
318 a = ser_readdata64(s);
319}
320template <typename Stream> inline void Unserialize(Stream &s, float &a) {
322}
323template <typename Stream> inline void Unserialize(Stream &s, double &a) {
325}
326template <typename Stream, size_t N>
327inline void Unserialize(Stream &s, int8_t (&a)[N]) {
328 s.read(MakeWritableByteSpan(a));
329}
330template <typename Stream, size_t N>
331inline void Unserialize(Stream &s, uint8_t (&a)[N]) {
332 s.read(MakeWritableByteSpan(a));
333}
334template <typename Stream, size_t N>
335inline void Unserialize(Stream &s, std::array<int8_t, N> &a) {
336 s.read(a.data(), N);
337}
338template <typename Stream, size_t N>
339inline void Unserialize(Stream &s, std::array<uint8_t, N> &a) {
340 s.read(MakeWritableByteSpan(a));
341}
342#ifndef CHAR_EQUALS_INT8
343template <typename Stream, size_t N>
344inline void Unserialize(Stream &s, char (&a)[N]) {
345 s.read(MakeWritableByteSpan(a));
346}
347template <typename Stream, size_t N>
348inline void Unserialize(Stream &s, std::array<char, N> &a) {
349 s.read(MakeWritableByteSpan(a));
350}
351#endif
352
353template <typename Stream> inline void Serialize(Stream &s, bool a) {
354 char f = a;
355 ser_writedata8(s, f);
356}
357template <typename Stream> inline void Unserialize(Stream &s, bool &a) {
358 char f = ser_readdata8(s);
359 a = f;
360}
361template <typename Stream>
363 s.read(AsWritableBytes(span));
364}
365
374 if (nSize < 253) {
375 return sizeof(uint8_t);
376 }
377 if (nSize <= std::numeric_limits<uint16_t>::max()) {
378 return sizeof(uint8_t) + sizeof(uint16_t);
379 }
380 if (nSize <= std::numeric_limits<uint32_t>::max()) {
381 return sizeof(uint8_t) + sizeof(uint32_t);
382 }
383
384 return sizeof(uint8_t) + sizeof(uint64_t);
385}
386
388
389template <typename Stream> void WriteCompactSize(Stream &os, uint64_t nSize) {
390 if (nSize < 253) {
392 } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
393 ser_writedata8(os, 253);
395 } else if (nSize <= std::numeric_limits<uint32_t>::max()) {
396 ser_writedata8(os, 254);
398 } else {
399 ser_writedata8(os, 255);
401 }
402 return;
403}
404
412template <typename Stream>
415 uint64_t nSizeRet = 0;
416 if (chSize < 253) {
418 } else if (chSize == 253) {
420 if (nSizeRet < 253) {
421 throw std::ios_base::failure("non-canonical ReadCompactSize()");
422 }
423 } else if (chSize == 254) {
425 if (nSizeRet < 0x10000u) {
426 throw std::ios_base::failure("non-canonical ReadCompactSize()");
427 }
428 } else {
430 if (nSizeRet < 0x100000000ULL) {
431 throw std::ios_base::failure("non-canonical ReadCompactSize()");
432 }
433 }
434 if (range_check && nSizeRet > MAX_SIZE) {
435 throw std::ios_base::failure("ReadCompactSize(): size too large");
436 }
437 return nSizeRet;
438}
439
475
476template <VarIntMode Mode, typename I> struct CheckVarIntMode {
477 constexpr CheckVarIntMode() {
478 static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value,
479 "Unsigned type required with mode DEFAULT.");
480 static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED ||
481 std::is_signed<I>::value,
482 "Signed type required with mode NONNEGATIVE_SIGNED.");
483 }
484};
485
486template <VarIntMode Mode, typename I>
487inline unsigned int GetSizeOfVarInt(I n) {
489 int nRet = 0;
490 while (true) {
491 nRet++;
492 if (n <= 0x7F) {
493 return nRet;
494 }
495 n = (n >> 7) - 1;
496 }
497}
498
499template <typename I> inline void WriteVarInt(CSizeComputer &os, I n);
500
501template <typename Stream, VarIntMode Mode, typename I>
502void WriteVarInt(Stream &os, I n) {
504 uint8_t tmp[(sizeof(n) * 8 + 6) / 7];
505 int len = 0;
506 while (true) {
507 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
508 if (n <= 0x7F) {
509 break;
510 }
511 n = (n >> 7) - 1;
512 len++;
513 }
514 do {
515 ser_writedata8(os, tmp[len]);
516 } while (len--);
517}
518
519template <typename Stream, VarIntMode Mode, typename I>
522 I n = 0;
523 while (true) {
525 if (n > (std::numeric_limits<I>::max() >> 7)) {
526 throw std::ios_base::failure("ReadVarInt(): size too large");
527 }
528 n = (n << 7) | (chData & 0x7F);
529 if ((chData & 0x80) == 0) {
530 return n;
531 }
532 if (n == std::numeric_limits<I>::max()) {
533 throw std::ios_base::failure("ReadVarInt(): size too large");
534 }
535 n++;
536 }
537}
538
543template <typename Formatter, typename T> class Wrapper {
544 static_assert(std::is_lvalue_reference<T>::value,
545 "Wrapper needs an lvalue reference type T");
546
547protected:
549
550public:
551 explicit Wrapper(T obj) : m_object(obj) {}
552 template <typename Stream> void Serialize(Stream &s) const {
553 Formatter().Ser(s, m_object);
554 }
555 template <typename Stream> void Unserialize(Stream &s) {
556 Formatter().Unser(s, m_object);
557 }
558};
559
573template <typename Formatter, typename T>
574static inline Wrapper<Formatter, T &> Using(T &&t) {
576}
577
578#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
579#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
580#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
581#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
582
586template <VarIntMode Mode> struct VarIntFormatter {
587 template <typename Stream, typename I> void Ser(Stream &s, I v) {
589 }
590
591 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
593 }
594};
595
606template <int Bytes, bool BigEndian = false> struct CustomUintFormatter {
607 static_assert(Bytes > 0 && Bytes <= 8,
608 "CustomUintFormatter Bytes out of range");
609 static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
610
611 template <typename Stream, typename I> void Ser(Stream &s, I v) {
612 if (v < 0 || v > MAX) {
613 throw std::ios_base::failure(
614 "CustomUintFormatter value out of range");
615 }
616 if (BigEndian) {
617 uint64_t raw = htobe64(v);
618 s.write({BytePtr(&raw) + 8 - Bytes, Bytes});
619 } else {
620 uint64_t raw = htole64(v);
621 s.write({BytePtr(&raw), Bytes});
622 }
623 }
624
625 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
626 using U = typename std::conditional<std::is_enum<I>::value,
627 std::underlying_type<I>,
628 std::common_type<I>>::type::type;
629 static_assert(std::numeric_limits<U>::max() >= MAX &&
630 std::numeric_limits<U>::min() <= 0,
631 "Assigned type too small");
632 uint64_t raw = 0;
633 if (BigEndian) {
634 s.read({BytePtr(&raw) + 8 - Bytes, Bytes});
635 v = static_cast<I>(be64toh(raw));
636 } else {
637 s.read({BytePtr(&raw), Bytes});
638 v = static_cast<I>(le64toh(raw));
639 }
640 }
641};
642
643template <int Bytes>
645
647template <bool RangeCheck> struct CompactSizeFormatter {
648 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
650 if (n < std::numeric_limits<I>::min() ||
651 n > std::numeric_limits<I>::max()) {
652 throw std::ios_base::failure("CompactSize exceeds limit of type");
653 }
654 v = n;
655 }
656
657 template <typename Stream, typename I> void Ser(Stream &s, I v) {
658 static_assert(std::is_unsigned<I>::value,
659 "CompactSize only supported for unsigned integers");
660 static_assert(std::numeric_limits<I>::max() <=
661 std::numeric_limits<uint64_t>::max(),
662 "CompactSize only supports 64-bit integers and below");
663
665 }
666};
667
668template <typename U, bool LOSSY = false> struct ChronoFormatter {
669 template <typename Stream, typename Tp> void Unser(Stream &s, Tp &tp) {
670 U u;
671 s >> u;
672 // Lossy deserialization does not make sense, so force Wnarrowing
673 tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
674 }
675 template <typename Stream, typename Tp> void Ser(Stream &s, Tp tp) {
676 if constexpr (LOSSY) {
677 s << U(tp.time_since_epoch().count());
678 } else {
679 s << U{tp.time_since_epoch().count()};
680 }
681 }
682};
683template <typename U> using LossyChronoFormatter = ChronoFormatter<U, true>;
684
685template <size_t Limit> struct LimitedStringFormatter {
686 template <typename Stream> void Unser(Stream &s, std::string &v) {
687 size_t size = ReadCompactSize(s);
688 if (size > Limit) {
689 throw std::ios_base::failure("String length limit exceeded");
690 }
691 v.resize(size);
692 if (size != 0) {
693 s.read(MakeWritableByteSpan(v));
694 }
695 }
696
697 template <typename Stream> void Ser(Stream &s, const std::string &v) {
698 s << v;
699 }
700};
701
718template <class Formatter> struct VectorFormatter {
719 template <typename Stream, typename V> void Ser(Stream &s, const V &v) {
721 WriteCompactSize(s, v.size());
722 for (const typename V::value_type &elem : v) {
723 formatter.Ser(s, elem);
724 }
725 }
726
727 template <typename Stream, typename V> void Unser(Stream &s, V &v) {
729 v.clear();
730 size_t size = ReadCompactSize(s);
731 size_t allocated = 0;
732 while (allocated < size) {
733 // For DoS prevention, do not blindly allocate as much as the stream
734 // claims to contain. Instead, allocate in 5MiB batches, so that an
735 // attacker actually needs to provide X MiB of data to make us
736 // allocate X+5 Mib.
737 static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE,
738 "Vector element size too large");
739 allocated =
740 std::min(size, allocated + MAX_VECTOR_ALLOCATE /
741 sizeof(typename V::value_type));
742 v.reserve(allocated);
743 while (v.size() < allocated) {
744 v.emplace_back();
745 formatter.Unser(s, v.back());
746 }
747 }
748 };
749};
750
763
764public:
765 template <typename Stream, typename I> void Ser(Stream &s, I v) {
766 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
767 throw std::ios_base::failure("differential value overflow");
768 }
770 m_shift = uint64_t(v) + 1;
771 }
772 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
774 m_shift += n;
775 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
776 m_shift < std::numeric_limits<I>::min() ||
777 m_shift > std::numeric_limits<I>::max()) {
778 throw std::ios_base::failure("differential value overflow");
779 }
780 v = I(m_shift++);
781 }
782};
783
795 template <typename Stream, typename T> void Ser(Stream &s, T v) {
796 DifferenceFormatter::Ser(s, v.index);
797 v.SerData(s);
798 }
799
800 template <typename Stream, typename T> void Unser(Stream &s, T &v) {
801 DifferenceFormatter::Unser(s, v.index);
802 v.UnserData(s);
803 }
804};
805
813template <typename Stream, typename C>
814void Serialize(Stream &os, const std::basic_string<C> &str);
815template <typename Stream, typename C>
816void Unserialize(Stream &is, std::basic_string<C> &str);
817
823template <typename Stream, unsigned int N, typename T>
824void Serialize_impl(Stream &os, const prevector<N, T> &v, const uint8_t &);
825template <typename Stream, unsigned int N, typename T, typename V>
826void Serialize_impl(Stream &os, const prevector<N, T> &v, const V &);
827template <typename Stream, unsigned int N, typename T>
828inline void Serialize(Stream &os, const prevector<N, T> &v);
829template <typename Stream, unsigned int N, typename T>
831template <typename Stream, unsigned int N, typename T, typename V>
832void Unserialize_impl(Stream &is, prevector<N, T> &v, const V &);
833template <typename Stream, unsigned int N, typename T>
834inline void Unserialize(Stream &is, prevector<N, T> &v);
835
841template <typename Stream, typename T, typename A>
842void Serialize_impl(Stream &os, const std::vector<T, A> &v, const uint8_t &);
843template <typename Stream, typename T, typename A>
844void Serialize_impl(Stream &os, const std::vector<T, A> &v, const bool &);
845template <typename Stream, typename T, typename A, typename V>
846void Serialize_impl(Stream &os, const std::vector<T, A> &v, const V &);
847template <typename Stream, typename T, typename A>
848inline void Serialize(Stream &os, const std::vector<T, A> &v);
849template <typename Stream, typename T, typename A>
850void Unserialize_impl(Stream &is, std::vector<T, A> &v, const uint8_t &);
851template <typename Stream, typename T, typename A, typename V>
852void Unserialize_impl(Stream &is, std::vector<T, A> &v, const V &);
853template <typename Stream, typename T, typename A>
854inline void Unserialize(Stream &is, std::vector<T, A> &v);
855
859template <typename Stream, typename K, typename T>
860void Serialize(Stream &os, const std::pair<K, T> &item);
861template <typename Stream, typename K, typename T>
862void Unserialize(Stream &is, std::pair<K, T> &item);
863
867template <typename Stream, typename K, typename T, typename Pred, typename A>
868void Serialize(Stream &os, const std::map<K, T, Pred, A> &m);
869template <typename Stream, typename K, typename T, typename Pred, typename A>
870void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
871
875template <typename Stream, typename K, typename Pred, typename A>
876void Serialize(Stream &os, const std::set<K, Pred, A> &m);
877template <typename Stream, typename K, typename Pred, typename A>
878void Unserialize(Stream &is, std::set<K, Pred, A> &m);
879
883template <typename Stream, typename T>
884void Serialize(Stream &os, const std::shared_ptr<const T> &p);
885template <typename Stream, typename T>
886void Unserialize(Stream &os, std::shared_ptr<const T> &p);
887
891template <typename Stream, typename T>
892void Serialize(Stream &os, const std::unique_ptr<const T> &p);
893template <typename Stream, typename T>
894void Unserialize(Stream &os, std::unique_ptr<const T> &p);
895
899template <typename Stream, typename T>
900void Serialize(Stream &os, const RCUPtr<const T> &p);
901template <typename Stream, typename T>
903
908template <typename Stream, typename T>
909inline void Serialize(Stream &os, const T &a) {
910 a.Serialize(os);
911}
912
913template <typename Stream, typename T>
914inline void Unserialize(Stream &is, T &&a) {
915 a.Unserialize(is);
916}
917
925 template <typename Stream, typename T>
926 static void Ser(Stream &s, const T &t) {
927 Serialize(s, t);
928 }
929
930 template <typename Stream, typename T> static void Unser(Stream &s, T &t) {
931 Unserialize(s, t);
932 }
933};
934
938template <typename Stream, typename C>
939void Serialize(Stream &os, const std::basic_string<C> &str) {
940 WriteCompactSize(os, str.size());
941 if (!str.empty()) {
942 os.write(MakeByteSpan(str));
943 }
944}
945
946template <typename Stream, typename C>
947void Unserialize(Stream &is, std::basic_string<C> &str) {
948 size_t nSize = ReadCompactSize(is);
949 str.resize(nSize);
950 if (nSize != 0) {
951 is.read(MakeWritableByteSpan(str));
952 }
953}
954
958template <typename Stream, unsigned int N, typename T>
959void Serialize_impl(Stream &os, const prevector<N, T> &v, const uint8_t &) {
960 WriteCompactSize(os, v.size());
961 if (!v.empty()) {
962 os.write(MakeByteSpan(v));
963 }
964}
965
966template <typename Stream, unsigned int N, typename T, typename V>
970
971template <typename Stream, unsigned int N, typename T>
972inline void Serialize(Stream &os, const prevector<N, T> &v) {
973 Serialize_impl(os, v, T());
974}
975
976template <typename Stream, unsigned int N, typename T>
978 // Limit size per read so bogus size value won't cause out of memory
979 v.clear();
980 size_t nSize = ReadCompactSize(is);
981 size_t i = 0;
982 while (i < nSize) {
983 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
985 is.read(AsWritableBytes(Span{&v[i], blk}));
986 i += blk;
987 }
988}
989
990template <typename Stream, unsigned int N, typename T, typename V>
994
995template <typename Stream, unsigned int N, typename T>
997 Unserialize_impl(is, v, T());
998}
999
1003template <typename Stream, typename T, typename A>
1004void Serialize_impl(Stream &os, const std::vector<T, A> &v, const uint8_t &) {
1005 WriteCompactSize(os, v.size());
1006 if (!v.empty()) {
1007 os.write(MakeByteSpan(v));
1008 }
1009}
1010
1011template <typename Stream, typename T, typename A>
1012void Serialize_impl(Stream &os, const std::vector<T, A> &v, const bool &) {
1013 // A special case for std::vector<bool>, as dereferencing
1014 // std::vector<bool>::const_iterator does not result in a const bool&
1015 // due to std::vector's special casing for bool arguments.
1016 WriteCompactSize(os, v.size());
1017 for (bool elem : v) {
1018 ::Serialize(os, elem);
1019 }
1020}
1021
1022template <typename Stream, typename T, typename A, typename V>
1023void Serialize_impl(Stream &os, const std::vector<T, A> &v, const V &) {
1025}
1026
1027template <typename Stream, typename T, typename A>
1028inline void Serialize(Stream &os, const std::vector<T, A> &v) {
1029 Serialize_impl(os, v, T());
1030}
1031
1032template <typename Stream, typename T, typename A>
1033void Unserialize_impl(Stream &is, std::vector<T, A> &v, const uint8_t &) {
1034 // Limit size per read so bogus size value won't cause out of memory
1035 v.clear();
1036 size_t nSize = ReadCompactSize(is);
1037 size_t i = 0;
1038 while (i < nSize) {
1039 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1040 v.resize(i + blk);
1041 is.read(AsWritableBytes(Span{&v[i], blk}));
1042 i += blk;
1043 }
1044}
1045
1046template <typename Stream, typename T, typename A, typename V>
1047void Unserialize_impl(Stream &is, std::vector<T, A> &v, const V &) {
1049}
1050
1051template <typename Stream, typename T, typename A>
1052inline void Unserialize(Stream &is, std::vector<T, A> &v) {
1053 Unserialize_impl(is, v, T());
1054}
1055
1059template <typename Stream, typename K, typename T>
1060void Serialize(Stream &os, const std::pair<K, T> &item) {
1061 Serialize(os, item.first);
1062 Serialize(os, item.second);
1063}
1064
1065template <typename Stream, typename K, typename T>
1066void Unserialize(Stream &is, std::pair<K, T> &item) {
1067 Unserialize(is, item.first);
1068 Unserialize(is, item.second);
1069}
1070
1074template <typename Stream, typename K, typename T, typename Pred, typename A>
1075void Serialize(Stream &os, const std::map<K, T, Pred, A> &m) {
1076 WriteCompactSize(os, m.size());
1077 for (const auto &entry : m) {
1078 Serialize(os, entry);
1079 }
1080}
1081
1082template <typename Stream, typename K, typename T, typename Pred, typename A>
1083void Unserialize(Stream &is, std::map<K, T, Pred, A> &m) {
1084 m.clear();
1085 size_t nSize = ReadCompactSize(is);
1086 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1087 for (size_t i = 0; i < nSize; i++) {
1088 std::pair<K, T> item;
1089 Unserialize(is, item);
1090 mi = m.insert(mi, item);
1091 }
1092}
1093
1097template <typename Stream, typename K, typename Pred, typename A>
1098void Serialize(Stream &os, const std::set<K, Pred, A> &m) {
1099 WriteCompactSize(os, m.size());
1100 for (const K &i : m) {
1101 Serialize(os, i);
1102 }
1103}
1104
1105template <typename Stream, typename K, typename Pred, typename A>
1106void Unserialize(Stream &is, std::set<K, Pred, A> &m) {
1107 m.clear();
1108 size_t nSize = ReadCompactSize(is);
1109 typename std::set<K, Pred, A>::iterator it = m.begin();
1110 for (size_t i = 0; i < nSize; i++) {
1111 K key;
1112 Unserialize(is, key);
1113 it = m.insert(it, key);
1114 }
1115}
1116
1120template <typename Stream, typename T>
1121void Serialize(Stream &os, const std::unique_ptr<const T> &p) {
1122 Serialize(os, *p);
1123}
1124
1125template <typename Stream, typename T>
1126void Unserialize(Stream &is, std::unique_ptr<const T> &p) {
1127 p.reset(new T(deserialize, is));
1128}
1129
1133template <typename Stream, typename T>
1134void Serialize(Stream &os, const std::shared_ptr<const T> &p) {
1135 Serialize(os, *p);
1136}
1137
1138template <typename Stream, typename T>
1139void Unserialize(Stream &is, std::shared_ptr<const T> &p) {
1140 p = std::make_shared<const T>(deserialize, is);
1141}
1142
1146template <typename Stream, typename T>
1148 Serialize(os, *p);
1149}
1150
1151template <typename Stream, typename T>
1155
1160 constexpr bool ForRead() const { return false; }
1161};
1163 constexpr bool ForRead() const { return true; }
1164};
1165
1179protected:
1180 size_t nSize;
1181
1182 const int nVersion;
1183
1184public:
1186
1187 void write(Span<const std::byte> src) { this->nSize += src.size(); }
1188
1190 void seek(size_t _nSize) { this->nSize += _nSize; }
1191
1192 template <typename T> CSizeComputer &operator<<(const T &obj) {
1193 ::Serialize(*this, obj);
1194 return (*this);
1195 }
1196
1197 size_t size() const { return nSize; }
1198
1199 int GetVersion() const { return nVersion; }
1200};
1201
1202template <typename Stream> void SerializeMany(Stream &s) {}
1203
1204template <typename Stream, typename Arg, typename... Args>
1205void SerializeMany(Stream &s, const Arg &arg, const Args &...args) {
1206 ::Serialize(s, arg);
1207 ::SerializeMany(s, args...);
1208}
1209
1210template <typename Stream> inline void UnserializeMany(Stream &s) {}
1211
1212template <typename Stream, typename Arg, typename... Args>
1213inline void UnserializeMany(Stream &s, Arg &&arg, Args &&...args) {
1214 ::Unserialize(s, arg);
1215 ::UnserializeMany(s, args...);
1216}
1217
1218template <typename Stream, typename... Args>
1220 const Args &...args) {
1221 ::SerializeMany(s, args...);
1222}
1223
1224template <typename Stream, typename... Args>
1226 Args &&...args) {
1227 ::UnserializeMany(s, args...);
1228}
1229
1230template <typename Stream, typename Type, typename Fn>
1231inline void SerRead(Stream &s, CSerActionSerialize ser_action, Type &&, Fn &&) {
1232}
1233
1234template <typename Stream, typename Type, typename Fn>
1236 Fn &&fn) {
1237 fn(s, std::forward<Type>(obj));
1238}
1239
1240template <typename Stream, typename Type, typename Fn>
1242 Fn &&fn) {
1243 fn(s, std::forward<Type>(obj));
1244}
1245
1246template <typename Stream, typename Type, typename Fn>
1248 Fn &&) {}
1249
1250template <typename I> inline void WriteVarInt(CSizeComputer &s, I n) {
1252}
1253
1255 s.seek(GetSizeOfCompactSize(nSize));
1256}
1257
1258template <typename T> size_t GetSerializeSize(const T &t, int nVersion = 0) {
1259 return (CSizeComputer(nVersion) << t).size();
1260}
1261
1262template <typename... T>
1263size_t GetSerializeSizeMany(int nVersion, const T &...t) {
1264 CSizeComputer sc(nVersion);
1265 SerializeMany(sc, t...);
1266 return sc.size();
1267}
1268
1269#endif // BITCOIN_SERIALIZE_H
GetSerializeSize implementations
Definition serialize.h:1178
CSizeComputer & operator<<(const T &obj)
Definition serialize.h:1192
void write(Span< const std::byte > src)
Definition serialize.h:1187
CSizeComputer(int nVersionIn)
Definition serialize.h:1185
size_t size() const
Definition serialize.h:1197
const int nVersion
Definition serialize.h:1182
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition serialize.h:1190
int GetVersion() const
Definition serialize.h:1199
Helper for differentially encoded Compact Size integers in lists.
Definition serialize.h:761
void Unser(Stream &s, I &v)
Definition serialize.h:772
void Ser(Stream &s, I v)
Definition serialize.h:765
Definition rcu.h:85
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition rcu.h:112
A Span is an object that can refer to a contiguous sequence of objects.
Definition span.h:93
constexpr std::size_t size() const noexcept
Definition span.h:209
Simple wrapper class to serialize objects using a formatter; used by Using().
Definition serialize.h:543
Wrapper(T obj)
Definition serialize.h:551
void Serialize(Stream &s) const
Definition serialize.h:552
void Unserialize(Stream &s)
Definition serialize.h:555
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition prevector.h:38
bool empty() const
Definition prevector.h:396
void clear()
Definition prevector.h:449
size_type size() const
Definition prevector.h:394
void resize_uninitialized(size_type new_size)
Definition prevector.h:490
uint16_t be16toh(uint16_t big_endian_16bits)
Definition endian.h:156
uint16_t htobe16(uint16_t host_16bits)
Definition endian.h:144
uint32_t le32toh(uint32_t little_endian_32bits)
Definition endian.h:186
uint32_t htobe32(uint32_t host_32bits)
Definition endian.h:168
uint16_t le16toh(uint16_t little_endian_16bits)
Definition endian.h:162
uint64_t htobe64(uint64_t host_64bits)
Definition endian.h:192
uint64_t be64toh(uint64_t big_endian_64bits)
Definition endian.h:204
uint32_t be32toh(uint32_t big_endian_32bits)
Definition endian.h:180
uint64_t htole64(uint64_t host_64bits)
Definition endian.h:198
uint32_t htole32(uint32_t host_32bits)
Definition endian.h:174
uint16_t htole16(uint16_t host_16bits)
Definition endian.h:150
uint64_t le64toh(uint64_t little_endian_64bits)
Definition endian.h:210
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
void SerializeMany(Stream &s)
Definition serialize.h:1202
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition serialize.h:37
uint8_t ser_readdata8(Stream &s)
Definition serialize.h:83
float ser_uint32_to_float(uint32_t y)
Definition serialize.h:134
I ReadVarInt(Stream &is)
Definition serialize.h:520
void ser_writedata32be(Stream &s, uint32_t obj)
Definition serialize.h:74
void WriteVarInt(CSizeComputer &os, I n)
Definition serialize.h:1250
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition serialize.h:474
@ NONNEGATIVE_SIGNED
void ser_writedata32(Stream &s, uint32_t obj)
Definition serialize.h:69
size_t GetSerializeSizeMany(int nVersion, const T &...t)
Definition serialize.h:1263
uint32_t GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
Definition serialize.h:373
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
Definition serialize.h:31
constexpr deserialize_type deserialize
Definition serialize.h:50
void ser_writedata16(Stream &s, uint16_t obj)
Definition serialize.h:59
uint32_t ser_float_to_uint32(float x)
Definition serialize.h:120
@ SER_DISK
Definition serialize.h:153
@ SER_NETWORK
Definition serialize.h:152
@ SER_GETHASH
Definition serialize.h:154
void Unserialize(Stream &, char)=delete
void Unserialize_impl(Stream &is, prevector< N, T > &v, const uint8_t &)
Definition serialize.h:977
X & ReadWriteAsHelper(X &x)
Convert the reference base type to X, without changing constness or reference type.
Definition serialize.h:159
void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action, const Args &...args)
Definition serialize.h:1219
void SerWrite(Stream &s, CSerActionSerialize ser_action, Type &&obj, Fn &&fn)
Definition serialize.h:1241
void ser_writedata16be(Stream &s, uint16_t obj)
Definition serialize.h:64
uint16_t ser_readdata16(Stream &s)
Definition serialize.h:88
uint64_t ser_readdata64(Stream &s)
Definition serialize.h:108
double ser_uint64_to_double(uint64_t y)
Definition serialize.h:127
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
Definition serialize.h:55
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition serialize.h:413
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
Definition serialize.h:574
unsigned int GetSizeOfVarInt(I n)
Definition serialize.h:487
uint32_t ser_readdata32(Stream &s)
Definition serialize.h:98
uint16_t ser_readdata16be(Stream &s)
Definition serialize.h:93
void SerRead(Stream &s, CSerActionSerialize ser_action, Type &&, Fn &&)
Definition serialize.h:1231
void Serialize_impl(Stream &os, const prevector< N, T > &v, const uint8_t &)
prevector prevectors of uint8_t are a special case and are intended to be serialized as a single opaq...
Definition serialize.h:959
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition serialize.h:1258
void UnserializeMany(Stream &s)
Definition serialize.h:1210
uint64_t ser_double_to_uint64(double x)
Definition serialize.h:113
void ser_writedata64(Stream &s, uint64_t obj)
Definition serialize.h:79
uint32_t ser_readdata32be(Stream &s)
Definition serialize.h:103
void Serialize(Stream &, char)=delete
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition serialize.h:1254
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
Definition span.h:297
const std::byte * BytePtr(const void *data)
Convert a data pointer to a std::byte data pointer.
Definition span.h:286
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition span.h:301
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition span.h:294
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition span.h:304
Support for SERIALIZE_METHODS and READWRITE macro.
Definition serialize.h:1159
constexpr bool ForRead() const
Definition serialize.h:1160
constexpr bool ForRead() const
Definition serialize.h:1163
constexpr CheckVarIntMode()
Definition serialize.h:477
void Unser(Stream &s, Tp &tp)
Definition serialize.h:669
void Ser(Stream &s, Tp tp)
Definition serialize.h:675
Formatter for integers in CompactSize format.
Definition serialize.h:647
void Unser(Stream &s, I &v)
Definition serialize.h:648
void Ser(Stream &s, I v)
Definition serialize.h:657
Serialization wrapper class for custom integers and enums.
Definition serialize.h:606
static constexpr uint64_t MAX
Definition serialize.h:609
void Ser(Stream &s, I v)
Definition serialize.h:611
void Unser(Stream &s, I &v)
Definition serialize.h:625
Default formatter.
Definition serialize.h:924
static void Ser(Stream &s, const T &t)
Definition serialize.h:926
static void Unser(Stream &s, T &t)
Definition serialize.h:930
Helper for a list of items containing a differentially encoded index as their first member.
Definition serialize.h:794
void Unser(Stream &s, T &v)
Definition serialize.h:800
void Ser(Stream &s, T v)
Definition serialize.h:795
void Unser(Stream &s, std::string &v)
Definition serialize.h:686
void Ser(Stream &s, const std::string &v)
Definition serialize.h:697
Serialization wrapper class for integers in VarInt format.
Definition serialize.h:586
void Ser(Stream &s, I v)
Definition serialize.h:587
void Unser(Stream &s, I &v)
Definition serialize.h:591
Formatter to serialize/deserialize vector elements using another formatter.
Definition serialize.h:718
void Unser(Stream &s, V &v)
Definition serialize.h:727
void Ser(Stream &s, const V &v)
Definition serialize.h:719
Dummy data type to identify deserializing constructors.
Definition serialize.h:49