6#ifndef BITCOIN_SERIALIZE_H
7#define BITCOIN_SERIALIZE_H
33static constexpr uint64_t
MAX_SIZE = 0x02000000;
57template <
typename Stream>
inline void ser_writedata8(Stream &s, uint8_t obj) {
60template <
typename Stream>
65template <
typename Stream>
70template <
typename Stream>
75template <
typename Stream>
80template <
typename Stream>
117 std::memcpy(&tmp, &x,
sizeof(x));
118 static_assert(
sizeof(tmp) ==
sizeof(x),
119 "double and uint64_t assumed to have the same size");
124 std::memcpy(&tmp, &x,
sizeof(x));
125 static_assert(
sizeof(tmp) ==
sizeof(x),
126 "float and uint32_t assumed to have the same size");
131 std::memcpy(&tmp, &y,
sizeof(y));
132 static_assert(
sizeof(tmp) ==
sizeof(y),
133 "double and uint64_t assumed to have the same size");
138 std::memcpy(&tmp, &y,
sizeof(y));
139 static_assert(
sizeof(tmp) ==
sizeof(y),
140 "float and uint32_t assumed to have the same size");
168#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
169#define READWRITEAS(type, obj) \
170 (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
171#define SER_READ(obj, code) \
173 s, ser_action, obj, \
174 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
175#define SER_WRITE(obj, code) \
176 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
196#define FORMATTER_METHODS(cls, obj) \
197 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
198 SerializationOps(obj, s, CSerActionSerialize()); \
200 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
201 SerializationOps(obj, s, CSerActionUnserialize()); \
203 template <typename Stream, typename Type, typename Operation> \
204 static inline void SerializationOps(Type &obj, Stream &s, \
205 Operation ser_action)
215#define SERIALIZE_METHODS(cls, obj) \
216 template <typename Stream> void Serialize(Stream &s) const { \
217 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
218 "Serialize type mismatch"); \
221 template <typename Stream> void Unserialize(Stream &s) { \
222 static_assert(std::is_same<cls &, decltype(*this)>::value, \
223 "Unserialize type mismatch"); \
226 FORMATTER_METHODS(cls, obj)
232concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
235template <
typename Stream, CharNotInt8 V>
void Serialize(Stream &, V) =
delete;
236template <
typename Stream>
void Serialize(Stream &s, std::byte a) {
239template <
typename Stream>
inline void Serialize(Stream &s, int8_t a) {
242template <
typename Stream>
inline void Serialize(Stream &s, uint8_t a) {
245template <
typename Stream>
inline void Serialize(Stream &s, int16_t a) {
248template <
typename Stream>
inline void Serialize(Stream &s, uint16_t a) {
251template <
typename Stream>
inline void Serialize(Stream &s, int32_t a) {
254template <
typename Stream>
inline void Serialize(Stream &s, uint32_t a) {
257template <
typename Stream>
inline void Serialize(Stream &s, int64_t a) {
260template <
typename Stream>
inline void Serialize(Stream &s, uint64_t a) {
263template <
typename Stream>
inline void Serialize(Stream &s,
float a) {
266template <
typename Stream>
inline void Serialize(Stream &s,
double a) {
269template <
typename Stream,
size_t N>
273template <
typename Stream, BasicByte B,
size_t N>
277template <
typename Stream,
size_t N>
278inline void Serialize(Stream &s,
const std::array<int8_t, N> &a) {
279 s.write(a.data(), N);
281template <
typename Stream,
size_t N>
282inline void Serialize(Stream &s,
const std::array<uint8_t, N> &a) {
285template <
typename Stream, BasicByte B, std::
size_t N>
289template <
typename Stream, BasicByte B>
295template <
typename Stream, CharNotInt8 V>
297template <
typename Stream>
void Unserialize(Stream &s, std::byte &a) {
300template <
typename Stream>
inline void Unserialize(Stream &s, int8_t &a) {
303template <
typename Stream>
inline void Unserialize(Stream &s, uint8_t &a) {
306template <
typename Stream>
inline void Unserialize(Stream &s, int16_t &a) {
309template <
typename Stream>
inline void Unserialize(Stream &s, uint16_t &a) {
312template <
typename Stream>
inline void Unserialize(Stream &s, int32_t &a) {
315template <
typename Stream>
inline void Unserialize(Stream &s, uint32_t &a) {
318template <
typename Stream>
inline void Unserialize(Stream &s, int64_t &a) {
321template <
typename Stream>
inline void Unserialize(Stream &s, uint64_t &a) {
324template <
typename Stream>
inline void Unserialize(Stream &s,
float &a) {
327template <
typename Stream>
inline void Unserialize(Stream &s,
double &a) {
330template <
typename Stream,
size_t N>
334template <
typename Stream, BasicByte B,
size_t N>
339template <
typename Stream>
inline void Serialize(Stream &s,
bool a) {
343template <
typename Stream>
inline void Unserialize(Stream &s,
bool &a) {
347template <
typename Stream, BasicByte B, std::
size_t N>
351template <
typename Stream, BasicByte B>
365 return sizeof(uint8_t);
367 if (
nSize <= std::numeric_limits<uint16_t>::max()) {
368 return sizeof(uint8_t) +
sizeof(uint16_t);
370 if (
nSize <= std::numeric_limits<uint32_t>::max()) {
371 return sizeof(uint8_t) +
sizeof(uint32_t);
374 return sizeof(uint8_t) +
sizeof(uint64_t);
382 }
else if (
nSize <= std::numeric_limits<uint16_t>::max()) {
385 }
else if (
nSize <= std::numeric_limits<uint32_t>::max()) {
402template <
typename Stream>
405 uint64_t nSizeRet = 0;
408 }
else if (chSize == 253) {
410 if (nSizeRet < 253) {
411 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
413 }
else if (chSize == 254) {
415 if (nSizeRet < 0x10000u) {
416 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
420 if (nSizeRet < 0x100000000ULL) {
421 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
424 if (range_check && nSizeRet >
MAX_SIZE) {
425 throw std::ios_base::failure(
"ReadCompactSize(): size too large");
469 "Unsigned type required with mode DEFAULT.");
471 std::is_signed<I>::value,
472 "Signed type required with mode NONNEGATIVE_SIGNED.");
476template <VarIntMode Mode,
typename I>
491template <
typename Stream, VarIntMode Mode,
typename I>
494 uint8_t tmp[(
sizeof(n) * 8 + 6) / 7];
497 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
509template <
typename Stream, VarIntMode Mode,
typename I>
515 if (n > (std::numeric_limits<I>::max() >> 7)) {
516 throw std::ios_base::failure(
"ReadVarInt(): size too large");
518 n = (n << 7) | (chData & 0x7F);
519 if ((chData & 0x80) == 0) {
522 if (n == std::numeric_limits<I>::max()) {
523 throw std::ios_base::failure(
"ReadVarInt(): size too large");
533template <
typename Formatter,
typename T>
class Wrapper {
534 static_assert(std::is_lvalue_reference<T>::value,
535 "Wrapper needs an lvalue reference type T");
542 template <
typename Stream>
void Serialize(Stream &s)
const {
563template <
typename Formatter,
typename T>
568#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
569#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
570#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
571#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
577 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
578 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
581 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
582 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
597 static_assert(Bytes > 0 && Bytes <= 8,
598 "CustomUintFormatter Bytes out of range");
599 static constexpr uint64_t
MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
601 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
602 if (v < 0 || v >
MAX) {
603 throw std::ios_base::failure(
604 "CustomUintFormatter value out of range");
608 s.write({
BytePtr(&raw) + 8 - Bytes, Bytes});
611 s.write({
BytePtr(&raw), Bytes});
615 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
616 using U =
typename std::conditional<std::is_enum<I>::value,
617 std::underlying_type<I>,
618 std::common_type<I>>::type::type;
619 static_assert(std::numeric_limits<U>::max() >=
MAX &&
620 std::numeric_limits<U>::min() <= 0,
621 "Assigned type too small");
624 s.read({
BytePtr(&raw) + 8 - Bytes, Bytes});
625 v =
static_cast<I
>(
be64toh(raw));
627 s.read({
BytePtr(&raw), Bytes});
628 v =
static_cast<I
>(
le64toh(raw));
638 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
639 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
640 if (n < std::numeric_limits<I>::min() ||
641 n > std::numeric_limits<I>::max()) {
642 throw std::ios_base::failure(
"CompactSize exceeds limit of type");
647 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
648 static_assert(std::is_unsigned<I>::value,
649 "CompactSize only supported for unsigned integers");
650 static_assert(std::numeric_limits<I>::max() <=
651 std::numeric_limits<uint64_t>::max(),
652 "CompactSize only supports 64-bit integers and below");
654 WriteCompactSize<Stream>(s, v);
659 template <
typename Stream,
typename Tp>
void Unser(Stream &s, Tp &tp) {
663 tp = Tp{
typename Tp::duration{
typename Tp::duration::rep{u}}};
665 template <
typename Stream,
typename Tp>
void Ser(Stream &s, Tp tp) {
666 if constexpr (LOSSY) {
667 s << U(tp.time_since_epoch().count());
669 s << U{tp.time_since_epoch().count()};
676 template <
typename Stream>
void Unser(Stream &s, std::string &v) {
679 throw std::ios_base::failure(
"String length limit exceeded");
687 template <
typename Stream>
void Ser(Stream &s,
const std::string &v) {
709 template <
typename Stream,
typename V>
void Ser(Stream &s,
const V &v) {
712 for (
const typename V::value_type &elem : v) {
713 formatter.Ser(s, elem);
717 template <
typename Stream,
typename V>
void Unser(Stream &s, V &v) {
721 size_t allocated = 0;
722 while (allocated < size) {
728 "Vector element size too large");
731 sizeof(
typename V::value_type));
732 v.reserve(allocated);
733 while (v.size() < allocated) {
735 formatter.Unser(s, v.back());
755 template <
typename Stream,
typename I>
void Ser(Stream &s, I v) {
756 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
757 throw std::ios_base::failure(
"differential value overflow");
762 template <
typename Stream,
typename I>
void Unser(Stream &s, I &v) {
765 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
766 m_shift < std::numeric_limits<I>::min() ||
767 m_shift > std::numeric_limits<I>::max()) {
768 throw std::ios_base::failure(
"differential value overflow");
785 template <
typename Stream,
typename T>
void Ser(Stream &s, T v) {
790 template <
typename Stream,
typename T>
void Unser(Stream &s, T &v) {
803template <
typename Stream,
typename C>
804void Serialize(Stream &os,
const std::basic_string<C> &str);
805template <
typename Stream,
typename C>
806void Unserialize(Stream &is, std::basic_string<C> &str);
811template <
typename Stream,
unsigned int N,
typename T>
813template <
typename Stream,
unsigned int N,
typename T>
819template <
typename Stream,
typename T,
typename A>
820inline void Serialize(Stream &os,
const std::vector<T, A> &v);
821template <
typename Stream,
typename T,
typename A>
822inline void Unserialize(Stream &is, std::vector<T, A> &v);
827template <
typename Stream,
typename K,
typename T>
828void Serialize(Stream &os,
const std::pair<K, T> &item);
829template <
typename Stream,
typename K,
typename T>
830void Unserialize(Stream &is, std::pair<K, T> &item);
835template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
836void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m);
837template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
838void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
843template <
typename Stream,
typename K,
typename Pred,
typename A>
844void Serialize(Stream &os,
const std::set<K, Pred, A> &m);
845template <
typename Stream,
typename K,
typename Pred,
typename A>
846void Unserialize(Stream &is, std::set<K, Pred, A> &m);
851template <
typename Stream,
typename T>
852void Serialize(Stream &os,
const std::shared_ptr<const T> &p);
853template <
typename Stream,
typename T>
854void Unserialize(Stream &os, std::shared_ptr<const T> &p);
859template <
typename Stream,
typename T>
860void Serialize(Stream &os,
const std::unique_ptr<const T> &p);
861template <
typename Stream,
typename T>
862void Unserialize(Stream &os, std::unique_ptr<const T> &p);
867template <
typename Stream,
typename T>
869template <
typename Stream,
typename T>
876template <
class T,
class Stream>
878template <
typename Stream,
typename T>
884template <
class T,
class Stream>
886template <
typename Stream,
typename T>
899 template <
typename Stream,
typename T>
900 static void Ser(Stream &s,
const T &t) {
904 template <
typename Stream,
typename T>
static void Unser(Stream &s, T &t) {
912template <
typename Stream,
typename C>
913void Serialize(Stream &os,
const std::basic_string<C> &str) {
920template <
typename Stream,
typename C>
932template <
typename Stream,
unsigned int N,
typename T>
943template <
typename Stream,
unsigned int N,
typename T>
952 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
965template <
typename Stream,
typename T,
typename A>
973 }
else if constexpr (std::is_same_v<T, bool>) {
978 for (
bool elem : v) {
986template <
typename Stream,
typename T,
typename A>
995 size_t blk = std::min(nSize - i,
size_t(1 + 4999999 /
sizeof(T)));
1008template <
typename Stream,
typename K,
typename T>
1014template <
typename Stream,
typename K,
typename T>
1023template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1024void Serialize(Stream &os,
const std::map<K, T, Pred, A> &m) {
1026 for (
const auto &entry : m) {
1031template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
1035 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1036 for (
size_t i = 0; i < nSize; i++) {
1037 std::pair<K, T> item;
1039 mi = m.insert(mi, item);
1046template <
typename Stream,
typename K,
typename Pred,
typename A>
1049 for (
const K &i : m) {
1054template <
typename Stream,
typename K,
typename Pred,
typename A>
1058 typename std::set<K, Pred, A>::iterator it = m.begin();
1059 for (
size_t i = 0; i < nSize; i++) {
1062 it = m.insert(it, key);
1069template <
typename Stream,
typename T>
1070void Serialize(Stream &os,
const std::unique_ptr<const T> &p) {
1074template <
typename Stream,
typename T>
1082template <
typename Stream,
typename T>
1083void Serialize(Stream &os,
const std::shared_ptr<const T> &p) {
1087template <
typename Stream,
typename T>
1095template <
typename Stream,
typename T>
1100template <
typename Stream,
typename T>
1139 void seek(
size_t _nSize) { this->nSize += _nSize; }
1153template <
typename Stream,
typename Arg,
typename... Args>
1161template <
typename Stream,
typename Arg,
typename... Args>
1167template <
typename Stream,
typename... Args>
1169 const Args &...args) {
1173template <
typename Stream,
typename... Args>
1179template <
typename Stream,
typename Type,
typename Fn>
1183template <
typename Stream,
typename Type,
typename Fn>
1186 fn(s, std::forward<Type>(obj));
1189template <
typename Stream,
typename Type,
typename Fn>
1192 fn(s, std::forward<Type>(obj));
1195template <
typename Stream,
typename Type,
typename Fn>
1200 s.
seek(GetSizeOfVarInt<I>(n));
1211template <
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)
If none of the specialized versions above matched, default to calling member function.
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 Serialize(Stream &, V)=delete
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
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 &&)
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 SERIALIZE_METHODS and READWRITE macro.
constexpr bool ForRead() const
constexpr bool ForRead() const
constexpr CheckVarIntMode()
Dummy data type to identify deserializing constructors.