6#ifndef BITCOIN_SERIALIZE_H
7#define BITCOIN_SERIALIZE_H
31static constexpr uint64_t
MAX_SIZE = 0x02000000;
55template <
typename Stream>
inline void ser_writedata8(Stream &s, uint8_t obj) {
58template <
typename Stream>
63template <
typename Stream>
68template <
typename Stream>
73template <
typename Stream>
78template <
typename Stream>
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");
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");
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");
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");
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) \
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; })
194#define FORMATTER_METHODS(cls, obj) \
195 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
196 SerializationOps(obj, s, CSerActionSerialize()); \
198 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
199 SerializationOps(obj, s, CSerActionUnserialize()); \
201 template <typename Stream, typename Type, typename Operation> \
202 static inline void SerializationOps(Type &obj, Stream &s, \
203 Operation ser_action)
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"); \
219 template <typename Stream> void Unserialize(Stream &s) { \
220 static_assert(std::is_same<cls &, decltype(*this)>::value, \
221 "Unserialize type mismatch"); \
224 FORMATTER_METHODS(cls, obj)
226#ifndef CHAR_EQUALS_INT8
228template <
typename Stream>
void Serialize(Stream &,
char) =
delete;
230template <
typename Stream>
inline void Serialize(Stream &s, int8_t a) {
233template <
typename Stream>
inline void Serialize(Stream &s, uint8_t a) {
236template <
typename Stream>
inline void Serialize(Stream &s, int16_t a) {
239template <
typename Stream>
inline void Serialize(Stream &s, uint16_t a) {
242template <
typename Stream>
inline void Serialize(Stream &s, int32_t a) {
245template <
typename Stream>
inline void Serialize(Stream &s, uint32_t a) {
248template <
typename Stream>
inline void Serialize(Stream &s, int64_t a) {
251template <
typename Stream>
inline void Serialize(Stream &s, uint64_t a) {
254template <
typename Stream>
inline void Serialize(Stream &s,
float a) {
257template <
typename Stream>
inline void Serialize(Stream &s,
double a) {
260template <
typename Stream,
size_t N>
264template <
typename Stream,
size_t N>
265inline void Serialize(Stream &s,
const uint8_t (&a)[N]) {
268template <
typename Stream,
size_t N>
269inline void Serialize(Stream &s,
const std::array<int8_t, N> &a) {
270 s.write(a.data(), N);
272template <
typename Stream,
size_t N>
273inline void Serialize(Stream &s,
const std::array<uint8_t, N> &a) {
276#ifndef CHAR_EQUALS_INT8
278template <
typename Stream>
void Unserialize(Stream &,
char) =
delete;
279template <
typename Stream,
size_t N>
283template <
typename Stream,
size_t N>
284inline void Serialize(Stream &s,
const std::array<char, N> &a) {
288template <
typename Stream>
292template <
typename Stream>
296template <
typename Stream>
inline void Unserialize(Stream &s, int8_t &a) {
299template <
typename Stream>
inline void Unserialize(Stream &s, uint8_t &a) {
302template <
typename Stream>
inline void Unserialize(Stream &s, int16_t &a) {
305template <
typename Stream>
inline void Unserialize(Stream &s, uint16_t &a) {
308template <
typename Stream>
inline void Unserialize(Stream &s, int32_t &a) {
311template <
typename Stream>
inline void Unserialize(Stream &s, uint32_t &a) {
314template <
typename Stream>
inline void Unserialize(Stream &s, int64_t &a) {
317template <
typename Stream>
inline void Unserialize(Stream &s, uint64_t &a) {
320template <
typename Stream>
inline void Unserialize(Stream &s,
float &a) {
323template <
typename Stream>
inline void Unserialize(Stream &s,
double &a) {
326template <
typename Stream,
size_t N>
330template <
typename Stream,
size_t N>
334template <
typename Stream,
size_t N>
338template <
typename Stream,
size_t N>
342#ifndef CHAR_EQUALS_INT8
343template <
typename Stream,
size_t N>
347template <
typename Stream,
size_t N>
353template <
typename Stream>
inline void Serialize(Stream &s,
bool a) {
357template <
typename Stream>
inline void Unserialize(Stream &s,
bool &a) {
361template <
typename Stream>
375 return sizeof(uint8_t);
377 if (
nSize <= std::numeric_limits<uint16_t>::max()) {
378 return sizeof(uint8_t) +
sizeof(uint16_t);
380 if (
nSize <= std::numeric_limits<uint32_t>::max()) {
381 return sizeof(uint8_t) +
sizeof(uint32_t);
384 return sizeof(uint8_t) +
sizeof(uint64_t);
392 }
else if (
nSize <= std::numeric_limits<uint16_t>::max()) {
395 }
else if (
nSize <= std::numeric_limits<uint32_t>::max()) {
412template <
typename Stream>
415 uint64_t nSizeRet = 0;
418 }
else if (chSize == 253) {
420 if (nSizeRet < 253) {
421 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
423 }
else if (chSize == 254) {
425 if (nSizeRet < 0x10000u) {
426 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
430 if (nSizeRet < 0x100000000ULL) {
431 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
434 if (range_check && nSizeRet >
MAX_SIZE) {
435 throw std::ios_base::failure(
"ReadCompactSize(): size too large");
479 "Unsigned type required with mode DEFAULT.");
481 std::is_signed<I>::value,
482 "Signed type required with mode NONNEGATIVE_SIGNED.");
486template <VarIntMode Mode,
typename I>
501template <
typename Stream, VarIntMode Mode,
typename I>
504 uint8_t tmp[(
sizeof(n) * 8 + 6) / 7];
507 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
519template <
typename Stream, VarIntMode Mode,
typename I>
525 if (n > (std::numeric_limits<I>::max() >> 7)) {
526 throw std::ios_base::failure(
"ReadVarInt(): size too large");
528 n = (n << 7) | (chData & 0x7F);
529 if ((chData & 0x80) == 0) {
532 if (n == std::numeric_limits<I>::max()) {
533 throw std::ios_base::failure(
"ReadVarInt(): size too large");
543template <
typename Formatter,
typename T>
class Wrapper {
544 static_assert(std::is_lvalue_reference<T>::value,
545 "Wrapper needs an lvalue reference type T");
552 template <
typename Stream>
void Serialize(Stream &s)
const {
573template <
typename Formatter,
typename T>
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)
587 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
588 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
591 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
592 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
607 static_assert(Bytes > 0 && Bytes <= 8,
608 "CustomUintFormatter Bytes out of range");
609 static constexpr uint64_t
MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
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");
618 s.write({
BytePtr(&raw) + 8 - Bytes, Bytes});
621 s.write({
BytePtr(&raw), Bytes});
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");
634 s.read({
BytePtr(&raw) + 8 - Bytes, Bytes});
635 v =
static_cast<I
>(
be64toh(raw));
637 s.read({
BytePtr(&raw), Bytes});
638 v =
static_cast<I
>(
le64toh(raw));
648 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
649 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
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");
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");
664 WriteCompactSize<Stream>(s, v);
669 template <
typename Stream,
typename Tp>
void Unser(Stream &s, Tp &tp) {
673 tp = Tp{
typename Tp::duration{
typename Tp::duration::rep{u}}};
675 template <
typename Stream,
typename Tp>
void Ser(Stream &s, Tp tp) {
676 if constexpr (LOSSY) {
677 s << U(tp.time_since_epoch().count());
679 s << U{tp.time_since_epoch().count()};
686 template <
typename Stream>
void Unser(Stream &s, std::string &v) {
689 throw std::ios_base::failure(
"String length limit exceeded");
697 template <
typename Stream>
void Ser(Stream &s,
const std::string &v) {
719 template <
typename Stream,
typename V>
void Ser(Stream &s,
const V &v) {
722 for (
const typename V::value_type &elem : v) {
723 formatter.Ser(s, elem);
727 template <
typename Stream,
typename V>
void Unser(Stream &s, V &v) {
731 size_t allocated = 0;
732 while (allocated < size) {
738 "Vector element size too large");
741 sizeof(
typename V::value_type));
742 v.reserve(allocated);
743 while (v.size() < allocated) {
745 formatter.Unser(s, v.back());
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");
772 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
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");
795 template <
typename Stream,
typename T>
void Ser(Stream &s, T v) {
800 template <
typename Stream,
typename T>
void Unser(Stream &s, T &v) {
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);
823template <
typename Stream,
unsigned int N,
typename T>
825template <
typename Stream,
unsigned int N,
typename T,
typename V>
827template <
typename Stream,
unsigned int N,
typename T>
829template <
typename Stream,
unsigned int N,
typename T>
831template <
typename Stream,
unsigned int N,
typename T,
typename V>
833template <
typename Stream,
unsigned int N,
typename T>
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>
851template <
typename Stream,
typename T,
typename A,
typename V>
853template <
typename Stream,
typename T,
typename A>
854inline void Unserialize(Stream &is, std::vector<T, A> &v);
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);
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);
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);
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);
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);
899template <
typename Stream,
typename T>
901template <
typename Stream,
typename T>
908template <
typename Stream,
typename T>
913template <
typename Stream,
typename T>
925 template <
typename Stream,
typename T>
926 static void Ser(Stream &s,
const T &t) {
930 template <
typename Stream,
typename T>
static void Unser(Stream &s, T &t) {
938template <
typename Stream,
typename C>
939void Serialize(Stream &os,
const std::basic_string<C> &str) {
946template <
typename Stream,
typename C>
958template <
typename Stream,
unsigned int N,
typename T>
966template <
typename Stream,
unsigned int N,
typename T,
typename V>
971template <
typename Stream,
unsigned int N,
typename T>
976template <
typename Stream,
unsigned int N,
typename T>
983 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
990template <
typename Stream,
unsigned int N,
typename T,
typename V>
995template <
typename Stream,
unsigned int N,
typename T>
1003template <
typename Stream,
typename T,
typename A>
1011template <
typename Stream,
typename T,
typename A>
1017 for (
bool elem : v) {
1022template <
typename Stream,
typename T,
typename A,
typename V>
1027template <
typename Stream,
typename T,
typename A>
1028inline void Serialize(Stream &os,
const std::vector<T, A> &v) {
1032template <
typename Stream,
typename T,
typename A>
1039 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1046template <
typename Stream,
typename T,
typename A,
typename V>
1051template <
typename Stream,
typename T,
typename A>
1059template <
typename Stream,
typename K,
typename T>
1065template <
typename Stream,
typename K,
typename T>
1074template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1075void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m) {
1077 for (
const auto &entry : m) {
1082template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
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;
1090 mi = m.insert(mi, item);
1097template <
typename Stream,
typename K,
typename Pred,
typename A>
1100 for (
const K &i : m) {
1105template <
typename Stream,
typename K,
typename Pred,
typename A>
1109 typename std::set<K, Pred, A>::iterator it = m.begin();
1110 for (
size_t i = 0; i < nSize; i++) {
1113 it = m.insert(it, key);
1120template <
typename Stream,
typename T>
1121void Serialize(Stream &os,
const std::unique_ptr<const T> &p) {
1125template <
typename Stream,
typename T>
1133template <
typename Stream,
typename T>
1134void Serialize(Stream &os,
const std::shared_ptr<const T> &p) {
1138template <
typename Stream,
typename T>
1146template <
typename Stream,
typename T>
1151template <
typename Stream,
typename T>
1190 void seek(
size_t _nSize) { this->nSize += _nSize; }
1204template <
typename Stream,
typename Arg,
typename... Args>
1212template <
typename Stream,
typename Arg,
typename... Args>
1218template <
typename Stream,
typename... Args>
1220 const Args &...args) {
1224template <
typename Stream,
typename... Args>
1230template <
typename Stream,
typename Type,
typename Fn>
1234template <
typename Stream,
typename Type,
typename Fn>
1237 fn(s, std::forward<Type>(obj));
1240template <
typename Stream,
typename Type,
typename Fn>
1243 fn(s, std::forward<Type>(obj));
1246template <
typename Stream,
typename Type,
typename Fn>
1251 s.
seek(GetSizeOfVarInt<I>(n));
1262template <
typename... T>
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.
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)
uint16_t be16toh(uint16_t big_endian_16bits)
uint16_t htobe16(uint16_t host_16bits)
uint32_t le32toh(uint32_t little_endian_32bits)
uint32_t htobe32(uint32_t host_32bits)
uint16_t le16toh(uint16_t little_endian_16bits)
uint64_t htobe64(uint64_t host_64bits)
uint64_t be64toh(uint64_t big_endian_64bits)
uint32_t be32toh(uint32_t big_endian_32bits)
uint64_t htole64(uint64_t host_64bits)
uint32_t htole32(uint32_t host_32bits)
uint16_t htole16(uint16_t host_16bits)
uint64_t le64toh(uint64_t little_endian_64bits)
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 &, char)=delete
void Unserialize_impl(Stream &is, prevector< N, T > &v, const uint8_t &)
X & ReadWriteAsHelper(X &x)
Convert the reference base type to X, without changing constness or reference type.
void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action, const Args &...args)
void SerWrite(Stream &s, CSerActionSerialize ser_action, Type &&obj, Fn &&fn)
void ser_writedata16be(Stream &s, uint16_t obj)
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.
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)
void SerRead(Stream &s, CSerActionSerialize ser_action, Type &&, Fn &&)
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...
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 Serialize(Stream &, char)=delete
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 SERIALIZE_METHODS and READWRITE macro.
constexpr bool ForRead() const
constexpr bool ForRead() const
constexpr CheckVarIntMode()
Dummy data type to identify deserializing constructors.