6#ifndef BITCOIN_SERIALIZE_H
7#define BITCOIN_SERIALIZE_H
34static constexpr uint64_t
MAX_SIZE = 0x02000000;
58template <
typename Stream>
inline void ser_writedata8(Stream &s, uint8_t obj) {
61template <
typename Stream>
66template <
typename Stream>
71template <
typename Stream>
76template <
typename Stream>
81template <
typename Stream>
118 std::memcpy(&tmp, &x,
sizeof(x));
119 static_assert(
sizeof(tmp) ==
sizeof(x),
120 "double and uint64_t assumed to have the same size");
125 std::memcpy(&tmp, &x,
sizeof(x));
126 static_assert(
sizeof(tmp) ==
sizeof(x),
127 "float and uint32_t assumed to have the same size");
132 std::memcpy(&tmp, &y,
sizeof(y));
133 static_assert(
sizeof(tmp) ==
sizeof(y),
134 "double and uint64_t assumed to have the same size");
139 std::memcpy(&tmp, &y,
sizeof(y));
140 static_assert(
sizeof(tmp) ==
sizeof(y),
141 "float and uint32_t assumed to have the same size");
181 static_assert(std::is_base_of_v<Out, In>);
185 static_assert(std::is_base_of_v<Out, In>);
189#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
190#define SER_READ(obj, code) \
192 s, ser_action, obj, \
193 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
194#define SER_WRITE(obj, code) \
195 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
215#define FORMATTER_METHODS(cls, obj) \
216 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
217 SerializationOps(obj, s, ActionSerialize()); \
219 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
220 SerializationOps(obj, s, ActionUnserialize()); \
222 template <typename Stream, typename Type, typename Operation> \
223 static void SerializationOps(Type &obj, Stream &s, Operation ser_action)
258#define FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
259 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
260 SerializationOps(obj, s, ActionSerialize{}, s.GetParams()); \
262 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
263 SerializationOps(obj, s, ActionUnserialize{}, s.GetParams()); \
265 template <typename Stream, typename Type, typename Operation> \
266 static void SerializationOps(Type &obj, Stream &s, Operation ser_action, \
267 const paramcls ¶mobj)
269#define BASE_SERIALIZE_METHODS(cls) \
270 template <typename Stream> void Serialize(Stream &s) const { \
271 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
272 "Serialize type mismatch"); \
275 template <typename Stream> void Unserialize(Stream &s) { \
276 static_assert(std::is_same<cls &, decltype(*this)>::value, \
277 "Unserialize type mismatch"); \
289#define SERIALIZE_METHODS(cls, obj) \
290 BASE_SERIALIZE_METHODS(cls) \
291 FORMATTER_METHODS(cls, obj)
298#define SERIALIZE_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
299 BASE_SERIALIZE_METHODS(cls) \
300 FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj)
306concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
309template <
typename Stream, CharNotInt8 V>
void Serialize(Stream &, V) =
delete;
310template <
typename Stream>
void Serialize(Stream &s, std::byte a) {
313template <
typename Stream>
inline void Serialize(Stream &s, int8_t a) {
316template <
typename Stream>
inline void Serialize(Stream &s, uint8_t a) {
319template <
typename Stream>
inline void Serialize(Stream &s, int16_t a) {
322template <
typename Stream>
inline void Serialize(Stream &s, uint16_t a) {
325template <
typename Stream>
inline void Serialize(Stream &s, int32_t a) {
328template <
typename Stream>
inline void Serialize(Stream &s, uint32_t a) {
331template <
typename Stream>
inline void Serialize(Stream &s, int64_t a) {
334template <
typename Stream>
inline void Serialize(Stream &s, uint64_t a) {
337template <
typename Stream>
inline void Serialize(Stream &s,
float a) {
340template <
typename Stream>
inline void Serialize(Stream &s,
double a) {
343template <
typename Stream,
size_t N>
347template <
typename Stream, BasicByte B,
size_t N>
351template <
typename Stream,
size_t N>
352inline void Serialize(Stream &s,
const std::array<int8_t, N> &a) {
353 s.write(a.data(), N);
355template <
typename Stream,
size_t N>
356inline void Serialize(Stream &s,
const std::array<uint8_t, N> &a) {
359template <
typename Stream, BasicByte B, std::
size_t N>
363template <
typename Stream, BasicByte B>
369template <
typename Stream, CharNotInt8 V>
371template <
typename Stream>
void Unserialize(Stream &s, std::byte &a) {
374template <
typename Stream>
inline void Unserialize(Stream &s, int8_t &a) {
377template <
typename Stream>
inline void Unserialize(Stream &s, uint8_t &a) {
380template <
typename Stream>
inline void Unserialize(Stream &s, int16_t &a) {
383template <
typename Stream>
inline void Unserialize(Stream &s, uint16_t &a) {
386template <
typename Stream>
inline void Unserialize(Stream &s, int32_t &a) {
389template <
typename Stream>
inline void Unserialize(Stream &s, uint32_t &a) {
392template <
typename Stream>
inline void Unserialize(Stream &s, int64_t &a) {
395template <
typename Stream>
inline void Unserialize(Stream &s, uint64_t &a) {
398template <
typename Stream>
inline void Unserialize(Stream &s,
float &a) {
401template <
typename Stream>
inline void Unserialize(Stream &s,
double &a) {
404template <
typename Stream,
size_t N>
408template <
typename Stream, BasicByte B,
size_t N>
413template <
typename Stream>
inline void Serialize(Stream &s,
bool a) {
417template <
typename Stream>
inline void Unserialize(Stream &s,
bool &a) {
421template <
typename Stream, BasicByte B, std::
size_t N>
425template <
typename Stream, BasicByte B>
439 return sizeof(uint8_t);
441 if (
nSize <= std::numeric_limits<uint16_t>::max()) {
442 return sizeof(uint8_t) +
sizeof(uint16_t);
444 if (
nSize <= std::numeric_limits<uint32_t>::max()) {
445 return sizeof(uint8_t) +
sizeof(uint32_t);
448 return sizeof(uint8_t) +
sizeof(uint64_t);
456 }
else if (
nSize <= std::numeric_limits<uint16_t>::max()) {
459 }
else if (
nSize <= std::numeric_limits<uint32_t>::max()) {
476template <
typename Stream>
479 uint64_t nSizeRet = 0;
482 }
else if (chSize == 253) {
484 if (nSizeRet < 253) {
485 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
487 }
else if (chSize == 254) {
489 if (nSizeRet < 0x10000u) {
490 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
494 if (nSizeRet < 0x100000000ULL) {
495 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
498 if (range_check && nSizeRet >
MAX_SIZE) {
499 throw std::ios_base::failure(
"ReadCompactSize(): size too large");
543 "Unsigned type required with mode DEFAULT.");
545 std::is_signed<I>::value,
546 "Signed type required with mode NONNEGATIVE_SIGNED.");
550template <VarIntMode Mode,
typename I>
565template <
typename Stream, VarIntMode Mode,
typename I>
568 uint8_t tmp[(
sizeof(n) * 8 + 6) / 7];
571 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
583template <
typename Stream, VarIntMode Mode,
typename I>
589 if (n > (std::numeric_limits<I>::max() >> 7)) {
590 throw std::ios_base::failure(
"ReadVarInt(): size too large");
592 n = (n << 7) | (chData & 0x7F);
593 if ((chData & 0x80) == 0) {
596 if (n == std::numeric_limits<I>::max()) {
597 throw std::ios_base::failure(
"ReadVarInt(): size too large");
607template <
typename Formatter,
typename T>
class Wrapper {
608 static_assert(std::is_lvalue_reference<T>::value,
609 "Wrapper needs an lvalue reference type T");
616 template <
typename Stream>
void Serialize(Stream &s)
const {
637template <
typename Formatter,
typename T>
642#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
643#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
644#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
645#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
651 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
652 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
655 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
656 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
671 static_assert(Bytes > 0 && Bytes <= 8,
672 "CustomUintFormatter Bytes out of range");
673 static constexpr uint64_t
MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
675 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
676 if (v < 0 || v >
MAX) {
677 throw std::ios_base::failure(
678 "CustomUintFormatter value out of range");
682 s.write({
BytePtr(&raw) + 8 - Bytes, Bytes});
685 s.write({
BytePtr(&raw), Bytes});
689 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
690 using U =
typename std::conditional<std::is_enum<I>::value,
691 std::underlying_type<I>,
692 std::common_type<I>>::type::type;
693 static_assert(std::numeric_limits<U>::max() >=
MAX &&
694 std::numeric_limits<U>::min() <= 0,
695 "Assigned type too small");
698 s.read({
BytePtr(&raw) + 8 - Bytes, Bytes});
701 s.read({
BytePtr(&raw), Bytes});
712 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
713 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
714 if (n < std::numeric_limits<I>::min() ||
715 n > std::numeric_limits<I>::max()) {
716 throw std::ios_base::failure(
"CompactSize exceeds limit of type");
721 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
722 static_assert(std::is_unsigned<I>::value,
723 "CompactSize only supported for unsigned integers");
724 static_assert(std::numeric_limits<I>::max() <=
725 std::numeric_limits<uint64_t>::max(),
726 "CompactSize only supports 64-bit integers and below");
728 WriteCompactSize<Stream>(s, v);
733 template <
typename Stream,
typename Tp>
void Unser(Stream &s, Tp &tp) {
737 tp = Tp{
typename Tp::duration{
typename Tp::duration::rep{u}}};
739 template <
typename Stream,
typename Tp>
void Ser(Stream &s, Tp tp) {
740 if constexpr (LOSSY) {
741 s << U(tp.time_since_epoch().count());
743 s << U{tp.time_since_epoch().count()};
750 template <
typename Stream>
void Unser(Stream &s, std::string &v) {
753 throw std::ios_base::failure(
"String length limit exceeded");
761 template <
typename Stream>
void Ser(Stream &s,
const std::string &v) {
783 template <
typename Stream,
typename V>
void Ser(Stream &s,
const V &v) {
786 for (
const typename V::value_type &elem : v) {
787 formatter.Ser(s, elem);
791 template <
typename Stream,
typename V>
void Unser(Stream &s, V &v) {
795 size_t allocated = 0;
796 while (allocated < size) {
802 "Vector element size too large");
805 sizeof(
typename V::value_type));
806 v.reserve(allocated);
807 while (v.size() < allocated) {
809 formatter.Unser(s, v.back());
829 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
830 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
831 throw std::ios_base::failure(
"differential value overflow");
836 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
839 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
840 m_shift < std::numeric_limits<I>::min() ||
841 m_shift > std::numeric_limits<I>::max()) {
842 throw std::ios_base::failure(
"differential value overflow");
859 template <
typename Stream,
typename T>
void Ser(Stream &s, T v) {
864 template <
typename Stream,
typename T>
void Unser(Stream &s, T &v) {
877template <
typename Stream,
typename C>
878void Serialize(Stream &os,
const std::basic_string<C> &str);
879template <
typename Stream,
typename C>
880void Unserialize(Stream &is, std::basic_string<C> &str);
885template <
typename Stream,
unsigned int N,
typename T>
887template <
typename Stream,
unsigned int N,
typename T>
893template <
typename Stream,
typename T,
typename A>
894inline void Serialize(Stream &os,
const std::vector<T, A> &v);
895template <
typename Stream,
typename T,
typename A>
896inline void Unserialize(Stream &is, std::vector<T, A> &v);
901template <
typename Stream,
typename K,
typename T>
902void Serialize(Stream &os,
const std::pair<K, T> &item);
903template <
typename Stream,
typename K,
typename T>
904void Unserialize(Stream &is, std::pair<K, T> &item);
909template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
910void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m);
911template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
912void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
917template <
typename Stream,
typename K,
typename Pred,
typename A>
918void Serialize(Stream &os,
const std::set<K, Pred, A> &m);
919template <
typename Stream,
typename K,
typename Pred,
typename A>
920void Unserialize(Stream &is, std::set<K, Pred, A> &m);
925template <
typename Stream,
typename T>
926void Serialize(Stream &os,
const std::shared_ptr<const T> &p);
927template <
typename Stream,
typename T>
928void Unserialize(Stream &os, std::shared_ptr<const T> &p);
933template <
typename Stream,
typename T>
934void Serialize(Stream &os,
const std::unique_ptr<const T> &p);
935template <
typename Stream,
typename T>
936void Unserialize(Stream &os, std::unique_ptr<const T> &p);
941template <
typename Stream,
typename T>
943template <
typename Stream,
typename T>
950template <
class T,
class Stream>
952template <
typename Stream,
typename T>
958template <
class T,
class Stream>
960template <
typename Stream,
typename T>
973 template <
typename Stream,
typename T>
974 static void Ser(Stream &s,
const T &t) {
978 template <
typename Stream,
typename T>
static void Unser(Stream &s, T &t) {
986template <
typename Stream,
typename C>
987void Serialize(Stream &os,
const std::basic_string<C> &str) {
994template <
typename Stream,
typename C>
1006template <
typename Stream,
unsigned int N,
typename T>
1017template <
typename Stream,
unsigned int N,
typename T>
1026 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1039template <
typename Stream,
typename T,
typename A>
1047 }
else if constexpr (std::is_same_v<T, bool>) {
1052 for (
bool elem : v) {
1060template <
typename Stream,
typename T,
typename A>
1069 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1082template <
typename Stream,
typename K,
typename T>
1088template <
typename Stream,
typename K,
typename T>
1097template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1098void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m) {
1100 for (
const auto &entry : m) {
1105template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1109 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1110 for (
size_t i = 0; i < nSize; i++) {
1111 std::pair<K, T> item;
1113 mi = m.insert(mi, item);
1120template <
typename Stream,
typename K,
typename Pred,
typename A>
1123 for (
const K &i : m) {
1128template <
typename Stream,
typename K,
typename Pred,
typename A>
1132 typename std::set<K, Pred, A>::iterator it = m.begin();
1133 for (
size_t i = 0; i < nSize; i++) {
1136 it = m.insert(it, key);
1143template <
typename Stream,
typename T>
1144void Serialize(Stream &os,
const std::unique_ptr<const T> &p) {
1148template <
typename Stream,
typename T>
1156template <
typename Stream,
typename T>
1157void Serialize(Stream &os,
const std::shared_ptr<const T> &p) {
1161template <
typename Stream,
typename T>
1169template <
typename Stream,
typename T>
1174template <
typename Stream,
typename T>
1214 void seek(
size_t _nSize) { this->nSize += _nSize; }
1228template <
typename Stream,
typename Arg,
typename... Args>
1236template <
typename Stream,
typename Arg,
typename... Args>
1242template <
typename Stream,
typename... Args>
1244 const Args &...args) {
1248template <
typename Stream,
typename... Args>
1254template <
typename Stream,
typename Type,
typename Fn>
1257template <
typename Stream,
typename Type,
typename Fn>
1260 fn(s, std::forward<Type>(obj));
1263template <
typename Stream,
typename Type,
typename Fn>
1266 fn(s, std::forward<Type>(obj));
1269template <
typename Stream,
typename Type,
typename Fn>
1273 s.
seek(GetSizeOfVarInt<I>(n));
1284template <
typename... T>
1327 static_assert(std::is_lvalue_reference<T>::value,
1328 "ParamsWrapper needs an lvalue reference type T");
1336 template <
typename Stream>
void Serialize(Stream &s)
const {
1353template <
typename Params,
typename T>
const CChainParams & Params()
Return the currently selected parameters.
GetSerializeSize implementations
CSizeComputer & operator<<(const T &obj)
void write(Span< const std::byte > src)
CSizeComputer(int nVersionIn)
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Wrapper that overrides the GetParams() function of a stream (and hides GetVersion/GetType).
ParamsStream(const Params ¶ms LIFETIMEBOUND, SubStream &substream LIFETIMEBOUND)
void write(Span< const std::byte > src)
ParamsStream & operator<<(const U &obj)
void read(Span< std::byte > dst)
const Params & GetParams() const
ParamsStream & operator>>(U &&obj)
Wrapper that serializes objects with the specified parameters.
void Unserialize(Stream &s)
void Serialize(Stream &s) const
ParamsWrapper(const Params ¶ms, T obj)
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
Simple wrapper class to serialize objects using a formatter; used by Using().
void Serialize(Stream &s) const
void Unserialize(Stream &s)
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
void resize_uninitialized(size_type new_size)
If none of the specialized versions above matched, default to calling member function.
BSWAP_CONSTEXPR uint32_t be32toh_internal(uint32_t big_endian_32bits)
BSWAP_CONSTEXPR uint16_t be16toh_internal(uint16_t big_endian_16bits)
BSWAP_CONSTEXPR uint64_t htobe64_internal(uint64_t host_64bits)
BSWAP_CONSTEXPR uint16_t htobe16_internal(uint16_t host_16bits)
BSWAP_CONSTEXPR uint32_t htole32_internal(uint32_t host_32bits)
BSWAP_CONSTEXPR uint16_t htole16_internal(uint16_t host_16bits)
BSWAP_CONSTEXPR uint64_t be64toh_internal(uint64_t big_endian_64bits)
BSWAP_CONSTEXPR uint16_t le16toh_internal(uint16_t little_endian_16bits)
BSWAP_CONSTEXPR uint64_t htole64_internal(uint64_t host_64bits)
BSWAP_CONSTEXPR uint64_t le64toh_internal(uint64_t little_endian_64bits)
BSWAP_CONSTEXPR uint32_t le32toh_internal(uint32_t little_endian_32bits)
BSWAP_CONSTEXPR uint32_t htobe32_internal(uint32_t host_32bits)
void Serialize(Stream &, V)=delete
void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&)
void SerializeMany(Stream &s)
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
uint8_t ser_readdata8(Stream &s)
float ser_uint32_to_float(uint32_t y)
void ser_writedata32be(Stream &s, uint32_t obj)
void WriteVarInt(CSizeComputer &os, I n)
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
void ser_writedata32(Stream &s, uint32_t obj)
size_t GetSerializeSizeMany(int nVersion, const T &...t)
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...
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...
constexpr deserialize_type deserialize
void ser_writedata16(Stream &s, uint16_t obj)
uint32_t ser_float_to_uint32(float x)
void Unserialize(Stream &, V)=delete
Out & AsBase(In &x)
Convert any argument to a reference to X, maintaining constness.
static auto WithParams(const Params ¶ms, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
void ser_writedata16be(Stream &s, uint16_t obj)
void SerReadWriteMany(Stream &s, ActionSerialize ser_action, const Args &...args)
uint16_t ser_readdata16(Stream &s)
uint64_t ser_readdata64(Stream &s)
double ser_uint64_to_double(uint64_t y)
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
void SerWrite(Stream &s, ActionSerialize ser_action, Type &&obj, Fn &&fn)
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
unsigned int GetSizeOfVarInt(I n)
uint32_t ser_readdata32(Stream &s)
uint16_t ser_readdata16be(Stream &s)
size_t GetSerializeSize(const T &t, int nVersion=0)
void UnserializeMany(Stream &s)
uint64_t ser_double_to_uint64(double x)
void ser_writedata64(Stream &s, uint64_t obj)
uint32_t ser_readdata32be(Stream &s)
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
const std::byte * BytePtr(const void *data)
Convert a data pointer to a std::byte data pointer.
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Span< const std::byte > AsBytes(Span< T > s) noexcept
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Support for all macros providing or using the ser_action parameter of the SerializationOps method.
constexpr bool ForRead() const
constexpr bool ForRead() const
constexpr CheckVarIntMode()
Dummy data type to identify deserializing constructors.