6#ifndef BITCOIN_SERIALIZE_H
7#define BITCOIN_SERIALIZE_H
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
260template <
typename Stream,
size_t N>
264template <
typename Stream,
size_t N>
268template <
typename Stream,
size_t N>
270 s.write(
a.data(),
N);
272template <
typename Stream,
size_t N>
276#ifndef CHAR_EQUALS_INT8
279template <
typename Stream,
size_t N>
283template <
typename Stream,
size_t N>
288template <
typename Stream>
292template <
typename Stream>
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>
361template <
typename Stream>
377 if (
nSize <= std::numeric_limits<uint16_t>::max()) {
380 if (
nSize <= std::numeric_limits<uint32_t>::max()) {
392 }
else if (
nSize <= std::numeric_limits<uint16_t>::max()) {
395 }
else if (
nSize <= std::numeric_limits<uint32_t>::max()) {
412template <
typename Stream>
418 }
else if (
chSize == 253) {
421 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
423 }
else if (
chSize == 254) {
426 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
431 throw std::ios_base::failure(
"non-canonical ReadCompactSize()");
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");
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) {
608 "CustomUintFormatter Bytes out of range");
611 template <
typename Stream,
typename I>
void Ser(
Stream &s,
I v) {
613 throw std::ios_base::failure(
614 "CustomUintFormatter value out of range");
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");
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");
673 tp =
Tp{
typename Tp::duration{
typename Tp::duration::rep{u}}};
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) {
738 "Vector element size too large");
741 sizeof(
typename V::value_type));
765 template <
typename Stream,
typename I>
void Ser(
Stream &s,
I v) {
767 throw std::ios_base::failure(
"differential value overflow");
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>
815template <
typename Stream,
typename C>
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>
843template <
typename Stream,
typename T,
typename A>
845template <
typename Stream,
typename T,
typename A,
typename V>
847template <
typename Stream,
typename T,
typename A>
849template <
typename Stream,
typename T,
typename A>
851template <
typename Stream,
typename T,
typename A,
typename V>
853template <
typename Stream,
typename T,
typename A>
859template <
typename Stream,
typename K,
typename T>
861template <
typename Stream,
typename K,
typename T>
867template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
869template <
typename Stream,
typename K,
typename T,
typename Pred,
typename A>
875template <
typename Stream,
typename K,
typename Pred,
typename A>
877template <
typename Stream,
typename K,
typename Pred,
typename A>
883template <
typename Stream,
typename T>
885template <
typename Stream,
typename T>
891template <
typename Stream,
typename T>
893template <
typename Stream,
typename T>
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>
930 template <
typename Stream,
typename T>
static void Unser(
Stream &s, T &
t) {
938template <
typename Stream,
typename C>
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>
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>
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>
1125template <
typename Stream,
typename T>
1133template <
typename Stream,
typename T>
1138template <
typename Stream,
typename T>
1146template <
typename Stream,
typename T>
1151template <
typename Stream,
typename T>
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>
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)
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...
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.