aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cryptonote_basic/tx_extra.h8
-rw-r--r--src/serialization/container.h4
-rw-r--r--src/serialization/debug_archive.h10
-rw-r--r--src/serialization/difficulty_type.h2
-rw-r--r--src/serialization/pair.h4
-rw-r--r--src/serialization/serialization.h125
-rw-r--r--src/serialization/tuple.h2
-rw-r--r--src/serialization/variant.h45
-rw-r--r--tests/unit_tests/serialization.cpp39
9 files changed, 87 insertions, 152 deletions
diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h
index af6ee5197..a29f126ee 100644
--- a/src/cryptonote_basic/tx_extra.h
+++ b/src/cryptonote_basic/tx_extra.h
@@ -52,7 +52,7 @@ namespace cryptonote
// load
template <template <bool> class Archive>
- bool do_serialize(Archive<false>& ar)
+ bool member_do_serialize(Archive<false>& ar)
{
// size - 1 - because of variant tag
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
@@ -73,7 +73,7 @@ namespace cryptonote
// store
template <template <bool> class Archive>
- bool do_serialize(Archive<true>& ar)
+ bool member_do_serialize(Archive<true>& ar)
{
if(TX_EXTRA_PADDING_MAX_COUNT < size)
return false;
@@ -129,7 +129,7 @@ namespace cryptonote
// load
template <template <bool> class Archive>
- bool do_serialize(Archive<false>& ar)
+ bool member_do_serialize(Archive<false>& ar)
{
std::string field;
if(!::do_serialize(ar, field))
@@ -142,7 +142,7 @@ namespace cryptonote
// store
template <template <bool> class Archive>
- bool do_serialize(Archive<true>& ar)
+ bool member_do_serialize(Archive<true>& ar)
{
std::ostringstream oss;
binary_archive<true> oar(oss);
diff --git a/src/serialization/container.h b/src/serialization/container.h
index 80e1892f2..393c66399 100644
--- a/src/serialization/container.h
+++ b/src/serialization/container.h
@@ -42,7 +42,7 @@ namespace serialization
typename std::enable_if<!use_container_varint<T>(), bool>::type
serialize_container_element(Archive& ar, T& e)
{
- return ::do_serialize(ar, e);
+ return do_serialize(ar, e);
}
template<typename Archive, typename T>
@@ -52,7 +52,7 @@ namespace serialization
static constexpr const bool previously_varint = std::is_same<uint64_t, T>() || std::is_same<uint32_t, T>();
if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
- return ::do_serialize(ar, e);
+ return do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}
diff --git a/src/serialization/debug_archive.h b/src/serialization/debug_archive.h
index ef3bb4345..f4df963db 100644
--- a/src/serialization/debug_archive.h
+++ b/src/serialization/debug_archive.h
@@ -42,14 +42,12 @@ struct debug_archive : public json_archive<W> {
};
template <class T>
-struct serializer<debug_archive<true>, T>
+static inline bool do_serialize(debug_archive<true> &ar, T &v)
{
- static void serialize(debug_archive<true> &ar, T &v)
- {
ar.begin_object();
ar.tag(variant_serialization_traits<debug_archive<true>, T>::get_tag());
- serializer<json_archive<true>, T>::serialize(ar, v);
+ do_serialize(static_cast<json_archive<true>&>(ar), v);
ar.end_object();
ar.stream() << std::endl;
- }
-};
+ return true;
+}
diff --git a/src/serialization/difficulty_type.h b/src/serialization/difficulty_type.h
index 37761839b..c071f287b 100644
--- a/src/serialization/difficulty_type.h
+++ b/src/serialization/difficulty_type.h
@@ -31,8 +31,6 @@
#include "cryptonote_basic/difficulty.h"
#include "serialization.h"
-template<> struct is_basic_type<cryptonote::difficulty_type> { typedef boost::true_type type; };
-
template <template <bool> class Archive>
inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
{
diff --git a/src/serialization/pair.h b/src/serialization/pair.h
index f21041fe8..888033fb9 100644
--- a/src/serialization/pair.h
+++ b/src/serialization/pair.h
@@ -47,7 +47,7 @@ namespace serialization
typename std::enable_if<!use_pair_varint<T>(), bool>::type
serialize_pair_element(Archive& ar, T& e)
{
- return ::do_serialize(ar, e);
+ return do_serialize(ar, e);
}
template<typename Archive, typename T>
@@ -57,7 +57,7 @@ namespace serialization
static constexpr const bool previously_varint = std::is_same<uint64_t, T>();
if (!previously_varint && ar.varint_bug_backward_compatibility_enabled() && !typename Archive::is_saving())
- return ::do_serialize(ar, e);
+ return do_serialize(ar, e);
ar.serialize_varint(e);
return true;
}
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index efe1270a4..2911aecb5 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -57,73 +57,30 @@
template <class T>
struct is_blob_type { typedef boost::false_type type; };
-/*! \struct has_free_serializer
- *
- * \brief a descriptor for dispatching serialize
- */
-template <class T>
-struct has_free_serializer { typedef boost::true_type type; };
-
-/*! \struct is_basic_type
- *
- * \brief a descriptor for dispatching serialize
- */
-template <class T>
-struct is_basic_type { typedef boost::false_type type; };
-
-template<typename F, typename S>
-struct is_basic_type<std::pair<F,S>> { typedef boost::true_type type; };
-template<>
-struct is_basic_type<std::string> { typedef boost::true_type type; };
-
-/*! \struct serializer
+/*! \fn do_serialize(Archive &ar, T &v)
*
- * \brief ... wouldn't a class be better?
+ * \brief main function for dispatching serialization for a given pair of archive and value types
*
- * \detailed The logic behind serializing data. Places the archive
- * data into the supplied parameter. This dispatches based on the
- * supplied \a T template parameter's traits of is_blob_type or it is
- * an integral (as defined by the is_integral trait). Depends on the
- * \a Archive parameter to have overloaded the serialize_blob(T v,
- * size_t size) and serialize_int(T v) base on which trait it
- * applied. When the class has neither types, it falls to the
- * overloaded method do_serialize(Archive ar) in T to do the work.
+ * Types marked true with is_blob_type<T> will be serialized as a blob, integral types will be
+ * serialized as integers, and types who have a `member_do_serialize` method will be serialized
+ * using that method. Booleans are serialized like blobs.
*/
template <class Archive, class T>
-struct serializer{
- static bool serialize(Archive &ar, T &v) {
- return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_basic_type<T>::type());
- }
- template<typename A>
- static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) {
- ar.serialize_blob(&v, sizeof(v));
- return true;
- }
- template<typename A>
- static bool serialize(Archive &ar, T &v, boost::true_type, boost::false_type, A a) {
- ar.serialize_int(v);
- return true;
- }
- static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::false_type) {
- //serialize_custom(ar, v, typename has_free_serializer<T>::type());
- return v.do_serialize(ar);
- }
- static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::true_type) {
- //serialize_custom(ar, v, typename has_free_serializer<T>::type());
- return do_serialize(ar, v);
- }
- static void serialize_custom(Archive &ar, T &v, boost::true_type) {
- }
-};
-
-/*! \fn do_serialize(Archive &ar, T &v)
- *
- * \brief just calls the serialize function defined for ar and v...
- */
+inline std::enable_if_t<is_blob_type<T>::type::value, bool> do_serialize(Archive &ar, T &v)
+{
+ ar.serialize_blob(&v, sizeof(v));
+ return true;
+}
template <class Archive, class T>
-inline bool do_serialize(Archive &ar, T &v)
+inline std::enable_if_t<boost::is_integral<T>::value, bool> do_serialize(Archive &ar, T &v)
{
- return ::serializer<Archive, T>::serialize(ar, v);
+ ar.serialize_int(v);
+ return true;
+}
+template <class Archive, class T>
+inline auto do_serialize(Archive &ar, T &v) -> decltype(v.member_do_serialize(ar), true)
+{
+ return v.member_do_serialize(ar);
}
template <class Archive>
inline bool do_serialize(Archive &ar, bool &v)
@@ -144,16 +101,6 @@ inline bool do_serialize(Archive &ar, bool &v)
typedef boost::true_type type; \
}
-/*! \macro FREE_SERIALIZER
- *
- * \brief adds the has_free_serializer to the type
- */
-#define FREE_SERIALIZER(T) \
- template<> \
- struct has_free_serializer<T> { \
- typedef boost::true_type type; \
- }
-
/*! \macro VARIANT_TAG
*
* \brief Adds the tag \tag to the \a Archive of \a Type
@@ -174,7 +121,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define BEGIN_SERIALIZE() \
template <bool W, template <bool> class Archive> \
- bool do_serialize(Archive<W> &ar) {
+ bool member_do_serialize(Archive<W> &ar) {
/*! \macro BEGIN_SERIALIZE_OBJECT
*
@@ -183,7 +130,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define BEGIN_SERIALIZE_OBJECT() \
template <bool W, template <bool> class Archive> \
- bool do_serialize(Archive<W> &ar) { \
+ bool member_do_serialize(Archive<W> &ar) { \
ar.begin_object(); \
bool r = do_serialize_object(ar); \
ar.end_object(); \
@@ -197,11 +144,6 @@ inline bool do_serialize(Archive &ar, bool &v)
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \
::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving())
-/*! \macro PREPARE_CUSTOM_DEQUE_SERIALIZATION
- */
-#define PREPARE_CUSTOM_DEQUE_SERIALIZATION(size, vec) \
- ::serialization::detail::prepare_custom_deque_serialization(size, vec, typename Archive<W>::is_saving())
-
/*! \macro END_SERIALIZE
* \brief self-explanatory
*/
@@ -209,16 +151,6 @@ inline bool do_serialize(Archive &ar, bool &v)
return ar.good(); \
}
-/*! \macro VALUE(f)
- * \brief the same as FIELD(f)
- */
-#define VALUE(f) \
- do { \
- ar.tag(#f); \
- bool r = ::do_serialize(ar, f); \
- if (!r || !ar.good()) return false; \
- } while(0);
-
/*! \macro FIELD_N(t,f)
*
* \brief serializes a field \a f tagged \a t
@@ -226,7 +158,7 @@ inline bool do_serialize(Archive &ar, bool &v)
#define FIELD_N(t, f) \
do { \
ar.tag(t); \
- bool r = ::do_serialize(ar, f); \
+ bool r = do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -237,7 +169,7 @@ inline bool do_serialize(Archive &ar, bool &v)
#define FIELD(f) \
do { \
ar.tag(#f); \
- bool r = ::do_serialize(ar, f); \
+ bool r = do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -247,7 +179,7 @@ inline bool do_serialize(Archive &ar, bool &v)
*/
#define FIELDS(f) \
do { \
- bool r = ::do_serialize(ar, f); \
+ bool r = do_serialize(ar, f); \
if (!r || !ar.good()) return false; \
} while(0);
@@ -317,17 +249,6 @@ namespace serialization {
vec.resize(size);
}
- template <typename T>
- void prepare_custom_deque_serialization(size_t size, std::deque<T>& vec, const boost::mpl::bool_<true>& /*is_saving*/)
- {
- }
-
- template <typename T>
- void prepare_custom_deque_serialization(size_t size, std::deque<T>& vec, const boost::mpl::bool_<false>& /*is_saving*/)
- {
- vec.resize(size);
- }
-
/*! \fn do_check_stream_state
*
* \brief self explanatory
diff --git a/src/serialization/tuple.h b/src/serialization/tuple.h
index e76ca0b99..d9592bc96 100644
--- a/src/serialization/tuple.h
+++ b/src/serialization/tuple.h
@@ -39,7 +39,7 @@ namespace serialization
template <typename Archive, class T>
bool serialize_tuple_element(Archive& ar, T& e)
{
- return ::do_serialize(ar, e);
+ return do_serialize(ar, e);
}
template <typename Archive>
diff --git a/src/serialization/variant.h b/src/serialization/variant.h
index 77d767a1c..1cf93c8cf 100644
--- a/src/serialization/variant.h
+++ b/src/serialization/variant.h
@@ -72,7 +72,7 @@ struct variant_reader
{
if(variant_serialization_traits<Archive, current_type>::get_tag() == t) {
current_type x;
- if(!::do_serialize(ar, x))
+ if(!do_serialize(ar, x))
{
ar.set_fail();
return false;
@@ -100,19 +100,13 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
}
};
-
-template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
-{
- typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
- typedef typename Archive<false>::variant_tag_type variant_tag_type;
- typedef typename variant_type::types types;
-
- static bool serialize(Archive<false> &ar, variant_type &v) {
- variant_tag_type t;
+template <template <bool> class Archive, typename... T>
+static bool do_serialize(Archive<false> &ar, boost::variant<T...> &v) {
+ using types = typename boost::variant<T...>::types;
+ typename Archive<false>::variant_tag_type t;
ar.begin_variant();
ar.read_variant_tag(t);
- if(!variant_reader<Archive<false>, variant_type,
+ if(!variant_reader<Archive<false>, boost::variant<T...>,
typename boost::mpl::begin<types>::type,
typename boost::mpl::end<types>::type>::read(ar, v, t))
{
@@ -121,27 +115,21 @@ struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
}
ar.end_variant();
return true;
- }
-};
+}
-template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
+template <template <bool> class Archive>
+struct variant_write_visitor : public boost::static_visitor<bool>
{
- typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> variant_type;
- //typedef typename Archive<true>::variant_tag_type variant_tag_type;
-
- struct visitor : public boost::static_visitor<bool>
- {
Archive<true> &ar;
- visitor(Archive<true> &a) : ar(a) { }
+ variant_write_visitor(Archive<true> &a) : ar(a) { }
template <class T>
bool operator ()(T &rv) const
{
ar.begin_variant();
ar.write_variant_tag(variant_serialization_traits<Archive<true>, T>::get_tag());
- if(!::do_serialize(ar, rv))
+ if(!do_serialize(ar, rv))
{
ar.set_fail();
return false;
@@ -149,9 +137,10 @@ struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
ar.end_variant();
return true;
}
- };
-
- static bool serialize(Archive<true> &ar, variant_type &v) {
- return boost::apply_visitor(visitor(ar), v);
- }
};
+
+template <template <bool> class Archive, typename... T>
+static bool do_serialize(Archive<true> &ar, boost::variant<T...> &v)
+{
+ return boost::apply_visitor(variant_write_visitor<Archive>(ar), v);
+}
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 49f1dc310..ab81acefc 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -59,9 +59,7 @@ struct Struct
};
template <class Archive>
-struct serializer<Archive, Struct>
-{
- static bool serialize(Archive &ar, Struct &s) {
+static bool do_serialize(Archive &ar, Struct &s) {
ar.begin_object();
ar.tag("a");
ar.serialize_int(s.a);
@@ -71,8 +69,7 @@ struct serializer<Archive, Struct>
ar.serialize_blob(s.blob, sizeof(s.blob));
ar.end_object();
return true;
- }
-};
+}
struct Struct1
{
@@ -122,6 +119,23 @@ bool try_parse(const string &blob)
return serialization::parse_binary(blob, s1);
}
+namespace example_namespace
+{
+ struct ADLExampleStruct
+ {
+ std::string msg;
+ };
+
+ template <class Archive>
+ static bool do_serialize(Archive &ar, ADLExampleStruct &aes)
+ {
+ ar.begin_object();
+ FIELD_N("custom_fieldname", aes.msg);
+ ar.end_object();
+ return ar.good();
+ }
+}
+
TEST(Serialization, BinaryArchiveInts) {
uint64_t x = 0xff00000000, x1;
@@ -1178,3 +1192,18 @@ TEST(Serialization, difficulty_type)
ASSERT_EQ(v_original, v_unserialized);
}
+
+TEST(Serialization, adl_free_function)
+{
+ std::stringstream ss;
+ json_archive<true> ar(ss);
+
+ const std::string msg = "Howdy, World!";
+ example_namespace::ADLExampleStruct aes{msg};
+
+ ASSERT_TRUE(serialization::serialize(ar, aes));
+
+ // VVVVVVVVVVVVVVVVVVVVVVVVVV weird string serialization artifact
+ const std::string expected = "{\"custom_fieldname\": " + std::to_string(msg.size()) + '"' + epee::string_tools::buff_to_hex_nodelimer(msg) + "\"}";
+ EXPECT_EQ(expected, ss.str());
+}