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");
168 static_assert(std::is_base_of_v<Out, In>);
172 static_assert(std::is_base_of_v<Out, In>);
176#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
177#define SER_READ(obj, code) \
179 s, ser_action, obj, \
180 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
181#define SER_WRITE(obj, code) \
182 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
202#define FORMATTER_METHODS(cls, obj) \
203 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
204 SerializationOps(obj, s, ActionSerialize()); \
206 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
207 SerializationOps(obj, s, ActionUnserialize()); \
209 template <typename Stream, typename Type, typename Operation> \
210 static void SerializationOps(Type &obj, Stream &s, Operation ser_action)
245#define FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
246 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
247 SerializationOps(obj, s, ActionSerialize{}, s.GetParams()); \
249 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
250 SerializationOps(obj, s, ActionUnserialize{}, s.GetParams()); \
252 template <typename Stream, typename Type, typename Operation> \
253 static void SerializationOps(Type &obj, Stream &s, Operation ser_action, \
254 const paramcls ¶mobj)
256#define BASE_SERIALIZE_METHODS(cls) \
257 template <typename Stream> void Serialize(Stream &s) const { \
258 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
259 "Serialize type mismatch"); \
262 template <typename Stream> void Unserialize(Stream &s) { \
263 static_assert(std::is_same<cls &, decltype(*this)>::value, \
264 "Unserialize type mismatch"); \
276#define SERIALIZE_METHODS(cls, obj) \
277 BASE_SERIALIZE_METHODS(cls) \
278 FORMATTER_METHODS(cls, obj)
285#define SERIALIZE_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
286 BASE_SERIALIZE_METHODS(cls) \
287 FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj)
293concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
301template <
typename Stream, CharNotInt8 V>
void Serialize(Stream &, V) =
delete;
302template <
typename Stream>
void Serialize(Stream &s, std::byte a) {
305template <
typename Stream>
inline void Serialize(Stream &s, int8_t a) {
308template <
typename Stream>
inline void Serialize(Stream &s, uint8_t a) {
311template <
typename Stream>
inline void Serialize(Stream &s, int16_t a) {
314template <
typename Stream>
inline void Serialize(Stream &s, uint16_t a) {
317template <
typename Stream>
inline void Serialize(Stream &s, int32_t a) {
320template <
typename Stream>
inline void Serialize(Stream &s, uint32_t a) {
323template <
typename Stream>
inline void Serialize(Stream &s, int64_t a) {
326template <
typename Stream>
inline void Serialize(Stream &s, uint64_t a) {
329template <
typename Stream>
inline void Serialize(Stream &s,
float a) {
332template <
typename Stream>
inline void Serialize(Stream &s,
double a) {
335template <
typename Stream,
size_t N>
339template <
typename Stream, BasicByte B,
size_t N>
343template <
typename Stream,
size_t N>
344inline void Serialize(Stream &s,
const std::array<int8_t, N> &a) {
345 s.write(a.data(), N);
347template <
typename Stream,
size_t N>
348inline void Serialize(Stream &s,
const std::array<uint8_t, N> &a) {
351template <
typename Stream, BasicByte B, std::
size_t N>
355template <
typename Stream, BasicByte B>
361template <
typename Stream, CharNotInt8 V>
363template <
typename Stream>
void Unserialize(Stream &s, std::byte &a) {
366template <
typename Stream>
inline void Unserialize(Stream &s, int8_t &a) {
369template <
typename Stream>
inline void Unserialize(Stream &s, uint8_t &a) {
372template <
typename Stream>
inline void Unserialize(Stream &s, int16_t &a) {
375template <
typename Stream>
inline void Unserialize(Stream &s, uint16_t &a) {
378template <
typename Stream>
inline void Unserialize(Stream &s, int32_t &a) {
381template <
typename Stream>
inline void Unserialize(Stream &s, uint32_t &a) {
384template <
typename Stream>
inline void Unserialize(Stream &s, int64_t &a) {
387template <
typename Stream>
inline void Unserialize(Stream &s, uint64_t &a) {
390template <
typename Stream>
inline void Unserialize(Stream &s,
float &a) {
393template <
typename Stream>
inline void Unserialize(Stream &s,
double &a) {
396template <
typename Stream,
size_t N>
400template <
typename Stream, BasicByte B,
size_t N>
405template <
typename Stream>
inline void Serialize(Stream &s,
bool a) {
409template <
typename Stream>
inline void Unserialize(Stream &s,
bool &a) {
413template <
typename Stream, BasicByte B, std::
size_t N>
417template <
typename Stream, BasicByte B>
431 return sizeof(uint8_t);
433 if (
nSize <= std::numeric_limits<uint16_t>::max()) {
434 return sizeof(uint8_t) +
sizeof(uint16_t);
436 if (
nSize <= std::numeric_limits<uint32_t>::max()) {
437 return sizeof(uint8_t) +
sizeof(uint32_t);
440 return sizeof(uint8_t) +
sizeof(uint64_t);
448 }
else if (
nSize <= std::numeric_limits<uint16_t>::max()) {
451 }
else if (
nSize <= std::numeric_limits<uint32_t>::max()) {
468template <
typename Stream>
471 uint64_t nSizeRet = 0;
474 }
else if (chSize == 253) {
476 if (nSizeRet < 253) {
477 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
479 }
else if (chSize == 254) {
481 if (nSizeRet < 0x10000u) {
482 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
486 if (nSizeRet < 0x100000000ULL) {
487 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
490 if (range_check && nSizeRet >
MAX_SIZE) {
491 throw std::ios_base::failure(
"ReadCompactSize(): size too large");
535 "Unsigned type required with mode DEFAULT.");
537 std::is_signed<I>::value,
538 "Signed type required with mode NONNEGATIVE_SIGNED.");
542template <VarIntMode Mode,
typename I>
557template <
typename Stream, VarIntMode Mode,
typename I>
560 uint8_t tmp[(
sizeof(n) * 8 + 6) / 7];
563 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
575template <
typename Stream, VarIntMode Mode,
typename I>
581 if (n > (std::numeric_limits<I>::max() >> 7)) {
582 throw std::ios_base::failure(
"ReadVarInt(): size too large");
584 n = (n << 7) | (chData & 0x7F);
585 if ((chData & 0x80) == 0) {
588 if (n == std::numeric_limits<I>::max()) {
589 throw std::ios_base::failure(
"ReadVarInt(): size too large");
599template <
typename Formatter,
typename T>
class Wrapper {
600 static_assert(std::is_lvalue_reference<T>::value,
601 "Wrapper needs an lvalue reference type T");
608 template <
typename Stream>
void Serialize(Stream &s)
const {
629template <
typename Formatter,
typename T>
634#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
635#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
636#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
637#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
643 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
644 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
647 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
648 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
663 static_assert(Bytes > 0 && Bytes <= 8,
664 "CustomUintFormatter Bytes out of range");
665 static constexpr uint64_t
MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
667 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
668 if (v < 0 || v >
MAX) {
669 throw std::ios_base::failure(
670 "CustomUintFormatter value out of range");
674 s.write({
BytePtr(&raw) + 8 - Bytes, Bytes});
677 s.write({
BytePtr(&raw), Bytes});
681 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
682 using U =
typename std::conditional<std::is_enum<I>::value,
683 std::underlying_type<I>,
684 std::common_type<I>>::type::type;
685 static_assert(std::numeric_limits<U>::max() >=
MAX &&
686 std::numeric_limits<U>::min() <= 0,
687 "Assigned type too small");
690 s.read({
BytePtr(&raw) + 8 - Bytes, Bytes});
693 s.read({
BytePtr(&raw), Bytes});
704 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
705 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
706 if (n < std::numeric_limits<I>::min() ||
707 n > std::numeric_limits<I>::max()) {
708 throw std::ios_base::failure(
"CompactSize exceeds limit of type");
713 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
714 static_assert(std::is_unsigned<I>::value,
715 "CompactSize only supported for unsigned integers");
716 static_assert(std::numeric_limits<I>::max() <=
717 std::numeric_limits<uint64_t>::max(),
718 "CompactSize only supports 64-bit integers and below");
720 WriteCompactSize<Stream>(s, v);
725 template <
typename Stream,
typename Tp>
void Unser(Stream &s, Tp &tp) {
729 tp = Tp{
typename Tp::duration{
typename Tp::duration::rep{u}}};
731 template <
typename Stream,
typename Tp>
void Ser(Stream &s, Tp tp) {
732 if constexpr (LOSSY) {
733 s << U(tp.time_since_epoch().count());
735 s << U{tp.time_since_epoch().count()};
742 template <
typename Stream>
void Unser(Stream &s, std::string &v) {
745 throw std::ios_base::failure(
"String length limit exceeded");
753 template <
typename Stream>
void Ser(Stream &s,
const std::string &v) {
775 template <
typename Stream,
typename V>
void Ser(Stream &s,
const V &v) {
778 for (
const typename V::value_type &elem : v) {
779 formatter.Ser(s, elem);
783 template <
typename Stream,
typename V>
void Unser(Stream &s, V &v) {
787 size_t allocated = 0;
788 while (allocated < size) {
794 "Vector element size too large");
797 sizeof(
typename V::value_type));
798 v.reserve(allocated);
799 while (v.size() < allocated) {
801 formatter.Unser(s, v.back());
821 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
822 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
823 throw std::ios_base::failure(
"differential value overflow");
828 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
831 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
832 m_shift < std::numeric_limits<I>::min() ||
833 m_shift > std::numeric_limits<I>::max()) {
834 throw std::ios_base::failure(
"differential value overflow");
851 template <
typename Stream,
typename T>
void Ser(Stream &s, T v) {
856 template <
typename Stream,
typename T>
void Unser(Stream &s, T &v) {
869template <
typename Stream,
typename C>
870void Serialize(Stream &os,
const std::basic_string<C> &str);
871template <
typename Stream,
typename C>
872void Unserialize(Stream &is, std::basic_string<C> &str);
877template <
typename Stream,
unsigned int N,
typename T>
879template <
typename Stream,
unsigned int N,
typename T>
885template <
typename Stream,
typename T,
typename A>
886inline void Serialize(Stream &os,
const std::vector<T, A> &v);
887template <
typename Stream,
typename T,
typename A>
888inline void Unserialize(Stream &is, std::vector<T, A> &v);
893template <
typename Stream,
typename K,
typename T>
894void Serialize(Stream &os,
const std::pair<K, T> &item);
895template <
typename Stream,
typename K,
typename T>
896void Unserialize(Stream &is, std::pair<K, T> &item);
901template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
902void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m);
903template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
904void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
909template <
typename Stream,
typename K,
typename Pred,
typename A>
910void Serialize(Stream &os,
const std::set<K, Pred, A> &m);
911template <
typename Stream,
typename K,
typename Pred,
typename A>
912void Unserialize(Stream &is, std::set<K, Pred, A> &m);
917template <
typename Stream,
typename T>
918void Serialize(Stream &os,
const std::shared_ptr<const T> &p);
919template <
typename Stream,
typename T>
920void Unserialize(Stream &os, std::shared_ptr<const T> &p);
925template <
typename Stream,
typename T>
926void Serialize(Stream &os,
const std::unique_ptr<const T> &p);
927template <
typename Stream,
typename T>
928void Unserialize(Stream &os, std::unique_ptr<const T> &p);
933template <
typename Stream,
typename T>
935template <
typename Stream,
typename T>
942template <
class T,
class Stream>
944template <
typename Stream,
typename T>
950template <
class T,
class Stream>
952template <
typename Stream,
typename T>
965 template <
typename Stream,
typename T>
966 static void Ser(Stream &s,
const T &t) {
970 template <
typename Stream,
typename T>
static void Unser(Stream &s, T &t) {
978template <
typename Stream,
typename C>
979void Serialize(Stream &os,
const std::basic_string<C> &str) {
986template <
typename Stream,
typename C>
998template <
typename Stream,
unsigned int N,
typename T>
1009template <
typename Stream,
unsigned int N,
typename T>
1018 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1031template <
typename Stream,
typename T,
typename A>
1039 }
else if constexpr (std::is_same_v<T, bool>) {
1044 for (
bool elem : v) {
1052template <
typename Stream,
typename T,
typename A>
1061 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1074template <
typename Stream,
typename K,
typename T>
1080template <
typename Stream,
typename K,
typename T>
1089template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1090void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m) {
1092 for (
const auto &entry : m) {
1097template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1101 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1102 for (
size_t i = 0; i < nSize; i++) {
1103 std::pair<K, T> item;
1105 mi = m.insert(mi, item);
1112template <
typename Stream,
typename K,
typename Pred,
typename A>
1115 for (
const K &i : m) {
1120template <
typename Stream,
typename K,
typename Pred,
typename A>
1124 typename std::set<K, Pred, A>::iterator it = m.begin();
1125 for (
size_t i = 0; i < nSize; i++) {
1128 it = m.insert(it, key);
1135template <
typename Stream,
typename T>
1136void Serialize(Stream &os,
const std::unique_ptr<const T> &p) {
1140template <
typename Stream,
typename T>
1148template <
typename Stream,
typename T>
1149void Serialize(Stream &os,
const std::shared_ptr<const T> &p) {
1153template <
typename Stream,
typename T>
1161template <
typename Stream,
typename T>
1166template <
typename Stream,
typename T>
1214template <
typename Stream,
typename... Args>
1219template <
typename Stream,
typename... Args>
1224template <
typename Stream,
typename... Args>
1226 const Args &...args) {
1230template <
typename Stream,
typename... Args>
1236template <
typename Stream,
typename Type,
typename Fn>
1239template <
typename Stream,
typename Type,
typename Fn>
1242 fn(s, std::forward<Type>(obj));
1245template <
typename Stream,
typename Type,
typename Fn>
1248 fn(s, std::forward<Type>(obj));
1251template <
typename Stream,
typename Type,
typename Fn>
1255 s.
seek(GetSizeOfVarInt<I>(n));
1302 static_assert(std::is_lvalue_reference<T>::value,
1303 "ParamsWrapper needs an lvalue reference type T");
1311 template <
typename Stream>
void Serialize(Stream &s)
const {
1328template <
typename Params,
typename T>
const CChainParams & Params()
Return the currently selected parameters.
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.
GetSerializeSize implementations
void write(Span< const std::byte > src)
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
SizeComputer & operator<<(const T &obj)
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)
size_t GetSerializeSize(const T &t)
void Serialize(Stream &, V)=delete
void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&)
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)
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
void ser_writedata32(Stream &s, uint32_t obj)
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...
void UnserializeMany(Stream &s, Args &&...args)
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.
void WriteVarInt(SizeComputer &os, I n)
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
void SerializeMany(Stream &s, const Args &...args)
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)
uint64_t ser_double_to_uint64(double x)
void ser_writedata64(Stream &s, uint64_t obj)
uint32_t ser_readdata32be(Stream &s)
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.