serialization: fix infinite loops and clean up dispatching
Resolves #8687
This commit is contained in:
parent
053ba2cf07
commit
a11e03afa6
|
@ -52,7 +52,7 @@ namespace cryptonote
|
||||||
|
|
||||||
// load
|
// load
|
||||||
template <template <bool> class Archive>
|
template <template <bool> class Archive>
|
||||||
bool do_serialize(Archive<false>& ar)
|
bool member_do_serialize(Archive<false>& ar)
|
||||||
{
|
{
|
||||||
// size - 1 - because of variant tag
|
// size - 1 - because of variant tag
|
||||||
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
|
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
|
||||||
|
@ -73,7 +73,7 @@ namespace cryptonote
|
||||||
|
|
||||||
// store
|
// store
|
||||||
template <template <bool> class Archive>
|
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)
|
if(TX_EXTRA_PADDING_MAX_COUNT < size)
|
||||||
return false;
|
return false;
|
||||||
|
@ -129,7 +129,7 @@ namespace cryptonote
|
||||||
|
|
||||||
// load
|
// load
|
||||||
template <template <bool> class Archive>
|
template <template <bool> class Archive>
|
||||||
bool do_serialize(Archive<false>& ar)
|
bool member_do_serialize(Archive<false>& ar)
|
||||||
{
|
{
|
||||||
std::string field;
|
std::string field;
|
||||||
if(!::do_serialize(ar, field))
|
if(!::do_serialize(ar, field))
|
||||||
|
@ -142,7 +142,7 @@ namespace cryptonote
|
||||||
|
|
||||||
// store
|
// store
|
||||||
template <template <bool> class Archive>
|
template <template <bool> class Archive>
|
||||||
bool do_serialize(Archive<true>& ar)
|
bool member_do_serialize(Archive<true>& ar)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
binary_archive<true> oar(oss);
|
binary_archive<true> oar(oss);
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace serialization
|
||||||
typename std::enable_if<!use_container_varint<T>(), bool>::type
|
typename std::enable_if<!use_container_varint<T>(), bool>::type
|
||||||
serialize_container_element(Archive& ar, T& e)
|
serialize_container_element(Archive& ar, T& e)
|
||||||
{
|
{
|
||||||
return ::do_serialize(ar, e);
|
return do_serialize(ar, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Archive, typename T>
|
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>();
|
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())
|
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);
|
ar.serialize_varint(e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,14 +42,12 @@ struct debug_archive : public json_archive<W> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
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.begin_object();
|
||||||
ar.tag(variant_serialization_traits<debug_archive<true>, T>::get_tag());
|
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.end_object();
|
||||||
ar.stream() << std::endl;
|
ar.stream() << std::endl;
|
||||||
}
|
return true;
|
||||||
};
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#include "cryptonote_basic/difficulty.h"
|
#include "cryptonote_basic/difficulty.h"
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
|
|
||||||
template<> struct is_basic_type<cryptonote::difficulty_type> { typedef boost::true_type type; };
|
|
||||||
|
|
||||||
template <template <bool> class Archive>
|
template <template <bool> class Archive>
|
||||||
inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
|
inline bool do_serialize(Archive<false>& ar, cryptonote::difficulty_type &diff)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace serialization
|
||||||
typename std::enable_if<!use_pair_varint<T>(), bool>::type
|
typename std::enable_if<!use_pair_varint<T>(), bool>::type
|
||||||
serialize_pair_element(Archive& ar, T& e)
|
serialize_pair_element(Archive& ar, T& e)
|
||||||
{
|
{
|
||||||
return ::do_serialize(ar, e);
|
return do_serialize(ar, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Archive, typename T>
|
template<typename Archive, typename T>
|
||||||
|
@ -57,7 +57,7 @@ namespace serialization
|
||||||
static constexpr const bool previously_varint = std::is_same<uint64_t, T>();
|
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())
|
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);
|
ar.serialize_varint(e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,73 +57,30 @@
|
||||||
template <class T>
|
template <class T>
|
||||||
struct is_blob_type { typedef boost::false_type type; };
|
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
|
|
||||||
*
|
|
||||||
* \brief ... wouldn't a class be better?
|
|
||||||
*
|
|
||||||
* \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.
|
|
||||||
*/
|
|
||||||
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)
|
/*! \fn do_serialize(Archive &ar, T &v)
|
||||||
*
|
*
|
||||||
* \brief just calls the serialize function defined for ar and v...
|
* \brief main function for dispatching serialization for a given pair of archive and value types
|
||||||
|
*
|
||||||
|
* 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>
|
template <class Archive, class T>
|
||||||
inline bool do_serialize(Archive &ar, T &v)
|
inline std::enable_if_t<is_blob_type<T>::type::value, bool> do_serialize(Archive &ar, T &v)
|
||||||
{
|
{
|
||||||
return ::serializer<Archive, T>::serialize(ar, v);
|
ar.serialize_blob(&v, sizeof(v));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <class Archive, class T>
|
||||||
|
inline std::enable_if_t<boost::is_integral<T>::value, bool> do_serialize(Archive &ar, T &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>
|
template <class Archive>
|
||||||
inline bool do_serialize(Archive &ar, bool &v)
|
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; \
|
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
|
/*! \macro VARIANT_TAG
|
||||||
*
|
*
|
||||||
* \brief Adds the tag \tag to the \a Archive of \a Type
|
* \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() \
|
#define BEGIN_SERIALIZE() \
|
||||||
template <bool W, template <bool> class Archive> \
|
template <bool W, template <bool> class Archive> \
|
||||||
bool do_serialize(Archive<W> &ar) {
|
bool member_do_serialize(Archive<W> &ar) {
|
||||||
|
|
||||||
/*! \macro BEGIN_SERIALIZE_OBJECT
|
/*! \macro BEGIN_SERIALIZE_OBJECT
|
||||||
*
|
*
|
||||||
|
@ -183,7 +130,7 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||||
*/
|
*/
|
||||||
#define BEGIN_SERIALIZE_OBJECT() \
|
#define BEGIN_SERIALIZE_OBJECT() \
|
||||||
template <bool W, template <bool> class Archive> \
|
template <bool W, template <bool> class Archive> \
|
||||||
bool do_serialize(Archive<W> &ar) { \
|
bool member_do_serialize(Archive<W> &ar) { \
|
||||||
ar.begin_object(); \
|
ar.begin_object(); \
|
||||||
bool r = do_serialize_object(ar); \
|
bool r = do_serialize_object(ar); \
|
||||||
ar.end_object(); \
|
ar.end_object(); \
|
||||||
|
@ -197,11 +144,6 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||||
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \
|
#define PREPARE_CUSTOM_VECTOR_SERIALIZATION(size, vec) \
|
||||||
::serialization::detail::prepare_custom_vector_serialization(size, vec, typename Archive<W>::is_saving())
|
::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
|
/*! \macro END_SERIALIZE
|
||||||
* \brief self-explanatory
|
* \brief self-explanatory
|
||||||
*/
|
*/
|
||||||
|
@ -209,16 +151,6 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||||
return ar.good(); \
|
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)
|
/*! \macro FIELD_N(t,f)
|
||||||
*
|
*
|
||||||
* \brief serializes a field \a f tagged \a t
|
* \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) \
|
#define FIELD_N(t, f) \
|
||||||
do { \
|
do { \
|
||||||
ar.tag(t); \
|
ar.tag(t); \
|
||||||
bool r = ::do_serialize(ar, f); \
|
bool r = do_serialize(ar, f); \
|
||||||
if (!r || !ar.good()) return false; \
|
if (!r || !ar.good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
@ -237,7 +169,7 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||||
#define FIELD(f) \
|
#define FIELD(f) \
|
||||||
do { \
|
do { \
|
||||||
ar.tag(#f); \
|
ar.tag(#f); \
|
||||||
bool r = ::do_serialize(ar, f); \
|
bool r = do_serialize(ar, f); \
|
||||||
if (!r || !ar.good()) return false; \
|
if (!r || !ar.good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
@ -247,7 +179,7 @@ inline bool do_serialize(Archive &ar, bool &v)
|
||||||
*/
|
*/
|
||||||
#define FIELDS(f) \
|
#define FIELDS(f) \
|
||||||
do { \
|
do { \
|
||||||
bool r = ::do_serialize(ar, f); \
|
bool r = do_serialize(ar, f); \
|
||||||
if (!r || !ar.good()) return false; \
|
if (!r || !ar.good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
|
@ -317,17 +249,6 @@ namespace serialization {
|
||||||
vec.resize(size);
|
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
|
/*! \fn do_check_stream_state
|
||||||
*
|
*
|
||||||
* \brief self explanatory
|
* \brief self explanatory
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace serialization
|
||||||
template <typename Archive, class T>
|
template <typename Archive, class T>
|
||||||
bool serialize_tuple_element(Archive& ar, T& e)
|
bool serialize_tuple_element(Archive& ar, T& e)
|
||||||
{
|
{
|
||||||
return ::do_serialize(ar, e);
|
return do_serialize(ar, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Archive>
|
template <typename Archive>
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct variant_reader
|
||||||
{
|
{
|
||||||
if(variant_serialization_traits<Archive, current_type>::get_tag() == t) {
|
if(variant_serialization_traits<Archive, current_type>::get_tag() == t) {
|
||||||
current_type x;
|
current_type x;
|
||||||
if(!::do_serialize(ar, x))
|
if(!do_serialize(ar, x))
|
||||||
{
|
{
|
||||||
ar.set_fail();
|
ar.set_fail();
|
||||||
return false;
|
return false;
|
||||||
|
@ -100,19 +100,13 @@ struct variant_reader<Archive, Variant, TBegin, TBegin>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <template <bool> class Archive, typename... T>
|
||||||
template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
static bool do_serialize(Archive<false> &ar, boost::variant<T...> &v) {
|
||||||
struct serializer<Archive<false>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
using types = typename boost::variant<T...>::types;
|
||||||
{
|
typename Archive<false>::variant_tag_type 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;
|
|
||||||
ar.begin_variant();
|
ar.begin_variant();
|
||||||
ar.read_variant_tag(t);
|
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::begin<types>::type,
|
||||||
typename boost::mpl::end<types>::type>::read(ar, v, t))
|
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();
|
ar.end_variant();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
template <template <bool> class Archive, BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
template <template <bool> class Archive>
|
||||||
struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
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;
|
Archive<true> &ar;
|
||||||
|
|
||||||
visitor(Archive<true> &a) : ar(a) { }
|
variant_write_visitor(Archive<true> &a) : ar(a) { }
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool operator ()(T &rv) const
|
bool operator ()(T &rv) const
|
||||||
{
|
{
|
||||||
ar.begin_variant();
|
ar.begin_variant();
|
||||||
ar.write_variant_tag(variant_serialization_traits<Archive<true>, T>::get_tag());
|
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();
|
ar.set_fail();
|
||||||
return false;
|
return false;
|
||||||
|
@ -149,9 +137,10 @@ struct serializer<Archive<true>, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>>
|
||||||
ar.end_variant();
|
ar.end_variant();
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -59,9 +59,7 @@ struct Struct
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
struct serializer<Archive, Struct>
|
static bool do_serialize(Archive &ar, Struct &s) {
|
||||||
{
|
|
||||||
static bool serialize(Archive &ar, Struct &s) {
|
|
||||||
ar.begin_object();
|
ar.begin_object();
|
||||||
ar.tag("a");
|
ar.tag("a");
|
||||||
ar.serialize_int(s.a);
|
ar.serialize_int(s.a);
|
||||||
|
@ -71,8 +69,7 @@ struct serializer<Archive, Struct>
|
||||||
ar.serialize_blob(s.blob, sizeof(s.blob));
|
ar.serialize_blob(s.blob, sizeof(s.blob));
|
||||||
ar.end_object();
|
ar.end_object();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct Struct1
|
struct Struct1
|
||||||
{
|
{
|
||||||
|
@ -122,6 +119,23 @@ bool try_parse(const string &blob)
|
||||||
return serialization::parse_binary(blob, s1);
|
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) {
|
TEST(Serialization, BinaryArchiveInts) {
|
||||||
uint64_t x = 0xff00000000, x1;
|
uint64_t x = 0xff00000000, x1;
|
||||||
|
|
||||||
|
@ -1178,3 +1192,18 @@ TEST(Serialization, difficulty_type)
|
||||||
|
|
||||||
ASSERT_EQ(v_original, v_unserialized);
|
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());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue