aboutsummaryrefslogtreecommitdiff
path: root/src/serialize.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2020-01-18 07:32:31 -0800
committerPieter Wuille <pieter.wuille@gmail.com>2020-01-18 07:43:22 -0800
commitca34c5cba5fbb9b046b074a234f06ecf6ed5d610 (patch)
tree5e99a5cd6a4c78e671d9306bcc33cdb7c1de06ee /src/serialize.h
parenta654626f076a72416a3d354218d7107571d6caaf (diff)
downloadbitcoin-ca34c5cba5fbb9b046b074a234f06ecf6ed5d610.tar.xz
Add FORMATTER_METHODS, similar to SERIALIZE_METHODS, but for formatters
Diffstat (limited to 'src/serialize.h')
-rw-r--r--src/serialize.h32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/serialize.h b/src/serialize.h
index 56c324c527..7fa669ebdb 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -200,6 +200,30 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
}
/**
+ * Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
+ *
+ * Both Ser and Unser are delegated to a single static method SerializationOps, which is polymorphic
+ * in the serialized/deserialized type (allowing it to be const when serializing, and non-const when
+ * deserializing).
+ *
+ * Example use:
+ * struct FooFormatter {
+ * FORMATTER_METHODS(Class, obj) { READWRITE(obj.val1, VARINT(obj.val2)); }
+ * }
+ * would define a class FooFormatter that defines a serialization of Class objects consisting
+ * of serializing its val1 member using the default serialization, and its val2 member using
+ * VARINT serialization. That FooFormatter can then be used in statements like
+ * READWRITE(Using<FooFormatter>(obj.bla)).
+ */
+#define FORMATTER_METHODS(cls, obj) \
+ template<typename Stream> \
+ static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, CSerActionSerialize()); } \
+ template<typename Stream> \
+ static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, CSerActionUnserialize()); } \
+ template<typename Stream, typename Type, typename Operation> \
+ static inline void SerializationOps(Type& obj, Stream& s, Operation ser_action) \
+
+/**
* Implement the Serialize and Unserialize methods by delegating to a single templated
* static method that takes the to-be-(de)serialized object as a parameter. This approach
* has the advantage that the constness of the object becomes a template parameter, and
@@ -211,17 +235,15 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
void Serialize(Stream& s) const \
{ \
static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
- SerializationOps(*this, s, CSerActionSerialize()); \
+ Ser(s, *this); \
} \
template<typename Stream> \
void Unserialize(Stream& s) \
{ \
static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
- SerializationOps(*this, s, CSerActionUnserialize()); \
+ Unser(s, *this); \
} \
- template<typename Stream, typename Type, typename Operation> \
- static inline void SerializationOps(Type& obj, Stream& s, Operation ser_action) \
-
+ FORMATTER_METHODS(cls, obj)
#ifndef CHAR_EQUALS_INT8
template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char