aboutsummaryrefslogtreecommitdiff
path: root/src/serialize.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2020-01-08 08:56:19 -0800
committerPieter Wuille <pieter.wuille@gmail.com>2020-01-13 08:24:44 -0800
commitca62563df341786d1d1809a037d8b592924e78c4 (patch)
treeceed2c69361857a6c44cfc33aec8c99c8782dab0 /src/serialize.h
parente8e79958a7b2a0bf1b02adcce9f4d811eac37dfc (diff)
downloadbitcoin-ca62563df341786d1d1809a037d8b592924e78c4.tar.xz
Add a generic approach for (de)serialization of objects using code in other classes
This adds the (internal) Wrapper class, and the Using function that uses it. Given a class F that implements Ser(stream, const object&) and Unser(stream, object&) functions, this permits writing e.g. READWRITE(Using<F>(object)).
Diffstat (limited to 'src/serialize.h')
-rw-r--r--src/serialize.h26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/serialize.h b/src/serialize.h
index c9e994f844..fd8626007a 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -442,6 +442,32 @@ I ReadVarInt(Stream& is)
}
}
+/** Simple wrapper class to serialize objects using a formatter; used by Using(). */
+template<typename Formatter, typename T>
+class Wrapper
+{
+ static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
+protected:
+ T m_object;
+public:
+ explicit Wrapper(T obj) : m_object(obj) {}
+ template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
+ template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
+};
+
+/** Cause serialization/deserialization of an object to be done using a specified formatter class.
+ *
+ * To use this, you need a class Formatter that has public functions Ser(stream, const object&) for
+ * serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside
+ * READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).
+ *
+ * This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is
+ * const during serialization, and non-const during deserialization, which maintains const
+ * correctness.
+ */
+template<typename Formatter, typename T>
+static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
+
#define VARINT(obj, ...) WrapVarInt<__VA_ARGS__>(REF(obj))
#define COMPACTSIZE(obj) CCompactSize(REF(obj))
#define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj))