[c++] Remove bond::customize<protocols>

`bond::customize<protocols>` has been removed. All the public APIs that require a protocol list (e.g. `bond::Marshal`) now accept an extra template argument `Protocols` which defaults to `bond::BuiltInProtocols`. Custom input streams now require `bond::type_id<>` to be specialized with a unique magic number.

Closes https://github.com/Microsoft/bond/pull/425
This commit is contained in:
Ara Ayvazyan 2017-06-12 17:59:44 -07:00 коммит произвёл Chad Walters
Родитель e81d51b33b
Коммит 5454d52ea0
62 изменённых файлов: 2354 добавлений и 1643 удалений

Просмотреть файл

@ -53,6 +53,11 @@ different versioning scheme, following the Haskell community's
and
[the bf example](https://github.com/Microsoft/bond/commit/11beaf5319639e4bdee96a25f95154e4fed93a75#diff-bdda0f39d99280d4858b4453906eea17)
for more details.
* **Breaking change** The `bond::customize<protocols>` has been removed. All the
public APIs that require a protocol list (e.g. `bond::Marshal`) now accept
an extra template argument `Protocols` which defaults to `bond::BuiltInProtocols`.
Custom input streams now require `bond::type_id<>` to be specialized with a
unique magic number. For more details please see [the bf example](https://github.com/Microsoft/bond/tree/master/examples/cpp/core/bf).
* Initial support for sending
[Bond objects over gRPC](https://microsoft.github.io/bond/manual/bond_over_grpc.html)
has been added.

Просмотреть файл

@ -8,6 +8,7 @@
#include <bond/core/traits.h>
#include <bond/stream/output_buffer.h>
#include <boost/variant.hpp>
#include <boost/mpl/if.hpp>
namespace bond { namespace comm

Просмотреть файл

@ -300,7 +300,7 @@ private:
// FIXME - handle Unmarshal errors
try
{
Unmarshal<Error, InputBuffer>(buffer, response.error);
Unmarshal(buffer, response.error);
}
catch (const bond::Exception&)
{

Просмотреть файл

@ -16,26 +16,26 @@ namespace detail
{
/// @brief Apply transform to serialized struct wrapped in bonded<T>
template <typename Transform, typename T, typename Reader>
template <typename Protocols, typename Transform, typename T, typename Reader>
typename boost::disable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded)
{
return bonded._Apply(transform);
return bonded.template _Apply<Protocols>(transform);
}
/// @brief Apply transform to serialized container wrapped in value<T, Reader>
template <typename Transform, typename T, typename Reader>
template <typename Protocols, typename Transform, typename T, typename Reader>
bool inline
ApplyTransform(const Transform& transform, const value<T, Reader>& value)
{
value._Apply(transform);
value.template _Apply<Protocols>(transform);
return true;
}
/// @brief Apply transform to an instance of a struct
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
typename boost::disable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const T& value)
{
@ -44,7 +44,7 @@ ApplyTransform(const Transform& transform, const T& value)
/// @brief Apply transform which can modify an instance of a struct
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
typename boost::enable_if<is_modifying_transform<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, T& value)
{
@ -53,23 +53,23 @@ ApplyTransform(const Transform& transform, T& value)
// Specializations for transform requiring double-pass
template <typename Transform, typename T, typename Reader>
template <typename Protocols, typename Transform, typename T, typename Reader>
typename boost::enable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded)
{
if (transform.NeedPass0())
return DoublePassApply(transform, bonded);
return DoublePassApply<Protocols>(transform, bonded);
else
return bonded._Apply(transform);
return bonded.template _Apply<Protocols>(transform);
}
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
typename boost::enable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const T& value)
{
if (transform.NeedPass0())
return DoublePassApply(transform, value);
return DoublePassApply<Protocols>(transform, value);
else
return StaticParser<const T&>(value).Apply(transform, typename schema<T>::type());
}
@ -77,16 +77,16 @@ ApplyTransform(const Transform& transform, const T& value)
} // namespace detail
template <typename Transform, typename T, typename boost::enable_if<is_modifying_transform<Transform> >::type* = nullptr>
template <typename Protocols, typename Transform, typename T, typename boost::enable_if<is_modifying_transform<Transform> >::type*>
bool Apply(const Transform& transform, T& value)
{
return detail::ApplyTransform(transform, value);
return detail::ApplyTransform<Protocols>(transform, value);
}
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
bool Apply(const Transform& transform, const T& value)
{
return detail::ApplyTransform(transform, value);
return detail::ApplyTransform<Protocols>(transform, value);
}
} // namespace bond

Просмотреть файл

@ -13,116 +13,116 @@ namespace bond
/// @brief Serialize an object using a protocol writer
///
template <typename T, typename Writer>
template <typename Protocols = BuiltInProtocols, typename T, typename Writer>
inline void Serialize(const T& obj, Writer& output)
{
Apply(Serializer<Writer>(output), obj);
Apply<Protocols>(Serializer<Writer, Protocols>(output), obj);
}
/// @brief Deserialize an object from a protocol reader
template <typename T, typename Reader>
template <typename Protocols = BuiltInProtocols, typename Reader, typename T>
inline void Deserialize(Reader input, T& obj)
{
Apply(To<T>(obj), bonded<T, Reader&>(input));
Apply<Protocols>(To<T, Protocols>(obj), bonded<T, Reader&>(input));
}
/// @brief Deserialize an object of type T from a protocol reader
template <typename T, typename Reader>
template <typename T, typename Protocols = BuiltInProtocols, typename Reader>
inline T Deserialize(Reader input)
{
T tmp;
Apply(To<T>(tmp), bonded<T, Reader&>(input));
Apply<Protocols>(To<T, Protocols>(tmp), bonded<T, Reader&>(input));
return tmp;
}
/// @brief Deserialize an object from a protocol reader using runtime schema
template <typename T, typename Reader>
template <typename Protocols = BuiltInProtocols, typename Reader, typename T>
inline void Deserialize(Reader input, T& obj, const RuntimeSchema& schema)
{
Apply(To<T>(obj), bonded<void, Reader&>(input, schema));
Apply<Protocols>(To<T, Protocols>(obj), bonded<void, Reader&>(input, schema));
}
/// @brief Deserialize an object of type T from a protocol reader using runtime schema
template <typename T, typename Reader>
template <typename T, typename Protocols = BuiltInProtocols, typename Reader>
inline T Deserialize(Reader input, const RuntimeSchema& schema)
{
T tmp;
Apply(To<T>(tmp), bonded<void, Reader&>(input, schema));
Apply<Protocols>(To<T, Protocols>(tmp), bonded<void, Reader&>(input, schema));
return tmp;
}
/// @brief Marshal an object using a protocol writer
template <typename T, typename Writer>
template <typename Protocols, typename T, typename Writer>
inline void Marshal(const T& obj, Writer& output)
{
Apply(Marshaler<Writer>(output), obj);
Apply<Protocols>(Marshaler<Writer, Protocols>(output), obj);
}
/// @brief Unmarshal an object from data stream
template <typename T, typename Buffer>
template <typename Protocols = BuiltInProtocols, typename Buffer, typename T>
inline void Unmarshal(Buffer input, T& obj)
{
SelectProtocolAndApply<T>(input, To<T>(obj));
SelectProtocolAndApply<T, Protocols>(input, To<T, Protocols>(obj));
}
/// @brief Unmarshal an object of type T from data stream
template <typename T, typename Buffer>
template <typename T, typename Protocols = BuiltInProtocols, typename Buffer>
inline T Unmarshal(Buffer input)
{
T tmp;
SelectProtocolAndApply<T>(input, To<T>(tmp));
SelectProtocolAndApply<T, Protocols>(input, To<T, Protocols>(tmp));
return tmp;
}
/// @brief Initialize a bonded<T> from data stream contained marshaled object
template <typename T, typename Buffer>
template <typename Protocols = BuiltInProtocols, typename Buffer, typename T>
inline void Unmarshal(Buffer input, bonded<T>& obj)
{
SelectProtocolAndApply<T>(input, boost::ref(obj));
SelectProtocolAndApply<T, Protocols>(input, boost::ref(obj));
}
/// @brief Unmarshal an object from data stream using a runtime schema
template <typename T, typename Buffer>
template <typename Protocols = BuiltInProtocols, typename Buffer, typename T>
inline void Unmarshal(Buffer input, T& obj, const RuntimeSchema& schema)
{
SelectProtocolAndApply(schema, input, To<T>(obj));
SelectProtocolAndApply<Protocols>(schema, input, To<T, Protocols>(obj));
}
/// @brief Unmarshal an object of type T from data stream using a runtime schema
template <typename T, typename Buffer>
template <typename T, typename Protocols = BuiltInProtocols, typename Buffer>
inline T Unmarshal(Buffer input, const RuntimeSchema& schema)
{
T tmp;
SelectProtocolAndApply(schema, input, To<T>(tmp));
SelectProtocolAndApply<Protocols>(schema, input, To<T, Protocols>(tmp));
return tmp;
}
/// @brief Initialize a bonded<T> from data stream contained marshaled object
/// using a runtime schema
template <typename T, typename Buffer>
template <typename Protocols = BuiltInProtocols, typename Buffer, typename T>
inline void Unmarshal(Buffer input, bonded<T>& obj, const RuntimeSchema& schema)
{
SelectProtocolAndApply(schema, input, boost::ref(obj));
SelectProtocolAndApply<Protocols>(schema, input, boost::ref(obj));
}
/// @brief Merge an object with serialize data and write the result using
/// a protocol writer
template <typename T, typename Reader, typename Writer>
template <typename Protocols = BuiltInProtocols, typename T, typename Reader, typename Writer>
inline void Merge(const T& obj, Reader input, Writer& output)
{
Apply(Merger<T, Writer>(obj, output), bonded<T>(input));
Apply<Protocols>(Merger<T, Writer, Protocols>(obj, output), bonded<T>(input));
}
}

Просмотреть файл

@ -4,8 +4,9 @@
#pragma once
#include "config.h"
#include <bond/core/bond_const_enum.h>
#include "detail/tags.h"
#include <stdint.h>
#include <boost/utility/enable_if.hpp>
namespace bond
{
@ -14,7 +15,7 @@ class blob;
class InputBuffer;
class RuntimeSchema;
struct ProtocolReader;
class ProtocolReader;
template <typename T, typename Reader = ProtocolReader>
class bonded;
@ -43,7 +44,9 @@ class DOMParser;
template <typename T>
class RequiredFieldValiadator;
template <typename T, typename Validator = RequiredFieldValiadator<T> >
struct BuiltInProtocols;
template <typename T, typename Protocols = BuiltInProtocols, typename Validator = RequiredFieldValiadator<T> >
class To;
template <typename T, typename Enable = void> struct
@ -62,4 +65,26 @@ struct Metadata;
struct qualified_name_tag;
}
template <typename Protocols = BuiltInProtocols, typename Transform, typename T, typename boost::enable_if<is_modifying_transform<Transform> >::type* = nullptr>
bool Apply(const Transform& transform, T& value);
template <typename Protocols = BuiltInProtocols, typename Transform, typename T>
bool Apply(const Transform& transform, const T& value);
template <typename Protocols = BuiltInProtocols, typename T, typename Writer>
inline void Marshal(const T& obj, Writer& output);
template <typename Writer, typename Protocols = BuiltInProtocols>
class Marshaler;
template <typename Protocols = BuiltInProtocols, typename Writer>
Marshaler<Writer, Protocols> MarshalTo(Writer& output);
template <typename Writer, typename Protocols = BuiltInProtocols>
class Serializer;
template <typename Protocols = BuiltInProtocols, typename Writer>
Serializer<Writer, Protocols> SerializeTo(Writer& output);
} // bond

Просмотреть файл

@ -12,12 +12,15 @@
namespace bond
{
template <typename Buffer>
class SimpleBinaryReader;
template <typename... T>
struct Protocols;
template <typename BufferT>
class CompactBinaryReader;
template <typename BufferT, typename MarshaledBondedProtocolsT = Protocols<CompactBinaryReader<BufferT> > >
class SimpleBinaryReader;
BOND_CONSTEXPR_OR_CONST uint16_t v1 = 0x0001;
BOND_CONSTEXPR_OR_CONST uint16_t v2 = 0x0002;

Просмотреть файл

@ -6,20 +6,22 @@
#include "config.h"
#include "protocol.h"
#include "runtime_schema.h"
#include "detail/protocol_visitors.h"
#include "bond_fwd.h"
#include "detail/double_pass.h"
#include "detail/protocol_visitors.h"
#include "detail/marshaled_bonded.h"
namespace bond
{
namespace detail
{
template <typename Transform, typename T, typename Reader>
template <typename Protocols, typename Transform, typename T, typename Reader>
typename boost::disable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded);
template <typename Transform, typename T, typename Reader>
template <typename Protocols, typename Transform, typename T, typename Reader>
typename boost::enable_if<need_double_pass<Transform>, bool>::type inline
ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded);
@ -33,7 +35,7 @@ is_marshaled_bonded
&& is_bonded<T>::value> {};
template <typename T, typename Buffer, typename Transform>
template <typename T, typename Protocols, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> SelectProtocolAndApply(
Buffer& input,
const Transform& transform);
@ -153,46 +155,38 @@ public:
}
/// @brief Serialize bonded using specified protocol writer
template <typename Writer>
template <typename Protocols = BuiltInProtocols, typename Writer>
void Serialize(Writer& output) const
{
Apply(SerializeTo(output), *this);
}
/// @brief Deserialize an object of type T
T Deserialize() const
{
T tmp;
Apply(To<T>(tmp), *this);
return tmp;
Apply<Protocols>(SerializeTo<Protocols>(output), *this);
}
/// @brief Deserialize an object of type X
template <typename X>
template <typename X = T, typename Protocols = BuiltInProtocols>
X Deserialize() const
{
X tmp;
Apply(To<X>(tmp), *this);
Apply<Protocols>(To<X, Protocols>(tmp), *this);
return tmp;
}
/// @brief Deserialize to an object of type X
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
void Deserialize(X& var) const
{
Apply(To<X>(var), *this);
Apply<Protocols>(To<X, Protocols>(var), *this);
}
/// @brief Deserialize to a bonded<U>
template <typename U>
template <typename Protocols = BuiltInProtocols, typename U>
typename boost::enable_if<is_marshaled_bonded<T, Reader, U> >::type
Deserialize(bonded<U>& var) const
{
_SelectProtocolAndApply(boost::ref(var));
_SelectProtocolAndApply<Protocols>(boost::ref(var));
}
template <typename U>
template <typename Protocols = BuiltInProtocols, typename U>
typename boost::disable_if<is_marshaled_bonded<T, Reader, U> >::type
Deserialize(bonded<U>& var) const
{
@ -201,10 +195,10 @@ public:
/// @brief Update bonded<T> payload by merging it with an object of type X
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
void Merge(const X& var)
{
detail::Merge(var, _data);
detail::Merge<Protocols>(var, _data);
}
@ -226,11 +220,11 @@ public:
}
template <typename Transform, typename U, typename ReaderT>
template <typename Protocols, typename Transform, typename U, typename ReaderT>
friend typename boost::disable_if<detail::need_double_pass<Transform>, bool>::type inline
detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
template <typename Transform, typename U, typename ReaderT>
template <typename Protocols, typename Transform, typename U, typename ReaderT>
friend typename boost::enable_if<detail::need_double_pass<Transform>, bool>::type inline
detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
@ -239,29 +233,29 @@ public:
private:
// Apply transform to serialized data
template <typename Transform>
template <typename Protocols, typename Transform>
typename boost::enable_if<is_marshaled_bonded<T, Reader, Transform>, bool>::type
_Apply(const Transform& transform) const
{
return _SelectProtocolAndApply(transform);
return _SelectProtocolAndApply<Protocols>(transform);
}
template <typename Transform>
template <typename Protocols, typename Transform>
typename boost::disable_if<is_marshaled_bonded<T, Reader, Transform>, bool>::type
_Apply(const Transform& transform) const
{
_skip = false;
return detail::Parse<T>(transform, _data, typename schema_for_passthrough<T>::type(), _schema.get(), _base);
return detail::Parse<T, Protocols>(transform, _data, typename schema_for_passthrough<T>::type(), _schema.get(), _base);
}
template <typename Transform>
template <typename Protocols, typename Transform>
bool _SelectProtocolAndApply(const Transform& transform) const
{
_skip = false;
auto input = CreateInputBuffer(_data.GetBuffer(), detail::ReadBlob(_data));
return SelectProtocolAndApply<typename remove_bonded<T>::type>(input, transform).second;
return SelectProtocolAndApply<typename remove_bonded<T>::type, Protocols>(input, transform).second;
}
Reader _data;

Просмотреть файл

@ -70,45 +70,45 @@ public:
/// @brief Serialize bonded using specified protocol writer
template <typename Writer>
template <typename Protocols = BuiltInProtocols, typename Writer>
typename boost::disable_if<uses_marshaled_bonded<typename Writer::Reader> >::type
Serialize(Writer& output) const
{
Apply(SerializeTo(output), *this);
Apply<Protocols>(SerializeTo<Protocols>(output), *this);
}
template <typename Writer>
template <typename Protocols = BuiltInProtocols, typename Writer>
typename boost::enable_if<uses_marshaled_bonded<typename Writer::Reader> >::type
Serialize(Writer& output) const
{
if (_schema.GetType().bonded_type)
detail::MarshalToBlob(*this, output);
detail::MarshalToBlob<Protocols>(*this, output);
else
Apply(SerializeTo(output), *this);
Apply<Protocols>(SerializeTo<Protocols>(output), *this);
}
/// @brief Deserialize an object of type T
template <typename T>
template <typename T, typename Protocols = BuiltInProtocols>
T Deserialize() const
{
T tmp;
Apply(To<T>(tmp), *this);
Apply<Protocols>(To<T, Protocols>(tmp), *this);
return tmp;
}
/// @brief Deserialize to an object of type T
template <typename T>
template <typename Protocols = BuiltInProtocols, typename T>
void Deserialize(T& var) const
{
Apply(To<T>(var), *this);
Apply<Protocols>(To<T, Protocols>(var), *this);
}
/// @brief Deserialize to a bonded<T>
template <typename T>
template <typename Protocols = BuiltInProtocols, typename T>
void Deserialize(bonded<T>& var) const
{
#ifdef _MSC_VER
@ -121,8 +121,8 @@ public:
#endif
{
bonded<T> tmp;
_SelectProtocolAndApply(boost::ref(tmp));
tmp.Deserialize(var);
_SelectProtocolAndApply<Protocols>(boost::ref(tmp));
tmp.template Deserialize<Protocols>(var);
}
else
{
@ -139,11 +139,11 @@ public:
}
template <typename Transform, typename U, typename ReaderT>
template <typename Protocols, typename Transform, typename U, typename ReaderT>
friend typename boost::disable_if<detail::need_double_pass<Transform>, bool>::type inline
detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
template <typename Transform, typename U, typename ReaderT>
template <typename Protocols, typename Transform, typename U, typename ReaderT>
friend typename boost::enable_if<detail::need_double_pass<Transform>, bool>::type inline
detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
@ -152,7 +152,7 @@ public:
private:
// Apply transform to serialized data
template <typename Transform>
template <typename Protocols, typename Transform>
bool _Apply(const Transform& transform) const
{
#ifdef _MSC_VER
@ -164,27 +164,27 @@ private:
#pragma warning(pop)
#endif
{
return _SelectProtocolAndApply(transform);
return _SelectProtocolAndApply<Protocols>(transform);
}
else
{
_skip = false;
return detail::Parse<void>(transform, _data, _schema, NULL, _base);
return detail::Parse<void, Protocols>(transform, _data, _schema, NULL, _base);
}
}
template <typename Transform>
template <typename Protocols, typename Transform>
typename boost::enable_if<uses_marshaled_bonded<Reader, Transform>, bool>::type
_SelectProtocolAndApply(const Transform& transform) const
{
_skip = false;
auto input = CreateInputBuffer(_data.GetBuffer(), detail::ReadBlob(_data));
return SelectProtocolAndApply(_schema, input, transform).second;
return SelectProtocolAndApply<Protocols>(_schema, input, transform).second;
}
template <typename Transform>
template <typename Protocols, typename Transform>
typename boost::disable_if<uses_marshaled_bonded<Reader, Transform>, bool>::type
_SelectProtocolAndApply(const Transform&) const
{

Просмотреть файл

@ -14,18 +14,4 @@ is_protocol_enabled
: false_type {};
struct protocols;
// User can modify set of protocols by specializing customize<protocols>
template <typename> struct
customize
{
template <typename T> struct
modify
{
typedef T type;
};
};
}

Просмотреть файл

@ -0,0 +1,311 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
/*
* This header implements bond::detail::any class which provides similar functionality to
* the boost::any which (1) uses user-defined CTTI instead of a built-in RTTI and (2) uses
* user-defined storage size for small object optimization.
*/
#pragma once
#include "mpl.h"
#include <bond/core/config.h>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/enable_if.hpp>
#include <cstdint>
#include <type_traits>
namespace bond
{
namespace detail
{
template <template <typename> class TypeId, std::size_t Size>
class any
{
BOOST_STATIC_ASSERT(Size >= sizeof(void*));
public:
any() BOND_NOEXCEPT
: _id{}
{}
any(const any& other)
{
emplace_uninitialized(other);
}
template <typename T>
any(const T& value)
{
emplace_uninitialized(value);
}
~any()
{
destroy();
}
any& operator=(const any& other)
{
return assign(other);
}
template <typename T>
any& operator=(const T& value)
{
return assign(value);
}
bool empty() const BOND_NOEXCEPT
{
return _id == 0;
}
explicit operator bool() const BOND_NOEXCEPT
{
return !empty();
}
template <typename T>
T* cast() BOND_NOEXCEPT
{
return TypeId<T>::value == _id ? functions::template table<T>::unsafe_cast(*this) : nullptr;
}
template <typename T>
const T* cast() const BOND_NOEXCEPT
{
return TypeId<T>::value == _id ? functions::template table<T>::unsafe_cast(*this) : nullptr;
}
bool operator==(const any& other) const
{
return _id == other._id && (empty() || _functions.compare(*this, other));
}
bool operator!=(const any& other) const
{
return !(*this == other);
}
private:
using storage = typename std::aligned_storage<Size>::type;
struct functions
{
void (*destroy)(any& x);
void (*assign)(any& x, const any& other);
void (*emplace_uninitialized)(any& x, const any& other);
bool (*compare)(const any& x, const any& y);
template <typename T, bool IsSmall>
struct impl;
template <typename T>
struct impl<T, true>
{
static T* unsafe_cast(any& x) BOND_NOEXCEPT
{
BOOST_ASSERT(TypeId<T>::value == x._id);
return static_cast<T*>(x.data());
}
static const T* unsafe_cast(const any& x) BOND_NOEXCEPT
{
BOOST_ASSERT(TypeId<T>::value == x._id);
return static_cast<const T*>(x.data());
}
static void emplace_uninitialized(any& x, const T& value)
{
new (x.data()) T{ value };
}
static void destroy(any& x)
{
unsafe_cast(x)->~T();
}
};
template <typename T>
struct impl<T, false>
{
static T* unsafe_cast(any& x) BOND_NOEXCEPT
{
BOOST_ASSERT(TypeId<T>::value == x._id);
return *static_cast<T**>(x.data());
}
static const T* unsafe_cast(const any& x) BOND_NOEXCEPT
{
BOOST_ASSERT(TypeId<T>::value == x._id);
return *static_cast<const T* const*>(x.data());
}
static void emplace_uninitialized(any& x, const T& value)
{
*static_cast<T**>(x.data()) = new T{ value };
}
static void destroy(any& x)
{
delete unsafe_cast(x);
}
};
template <typename T>
struct table : impl<T, (sizeof(T) <= sizeof(storage))>
{
BOOST_STATIC_ASSERT(TypeId<T>::value != 0);
using base = impl<T, (sizeof(T) <= sizeof(storage))>;
template <typename U = T, typename boost::enable_if<std::is_copy_assignable<U> >::type* = nullptr>
static void assign(any& x, const T& value)
{
*base::unsafe_cast(x) = value;
}
template <typename U = T, typename boost::disable_if<std::is_copy_assignable<U> >::type* = nullptr>
static void assign(any& x, const T& value)
{
// TODO: Cache allocated buffer and reuse.
base::destroy(x);
emplace_uninitialized(x, value);
}
static void emplace_uninitialized(any& x, const T& value)
{
base::emplace_uninitialized(x, value);
x._id = TypeId<T>::value; // Update the id if emplace_uninitialized did not throw.
}
static functions make() BOND_NOEXCEPT
{
return
{
base::destroy,
[](any& x, const any& other) { assign(x, *base::unsafe_cast(other)); },
[](any& x, const any& other) { emplace_uninitialized(x, *base::unsafe_cast(other)); },
[](const any& x, const any& y) { return *base::unsafe_cast(x) == *base::unsafe_cast(y); }
};
}
};
};
const void* data() const BOND_NOEXCEPT
{
return &_storage;
}
void* data() BOND_NOEXCEPT
{
return &_storage;
}
/// The precondition is that *this is uninitialized (or destroyed).
template <typename T>
void emplace_uninitialized(const T& value)
{
functions::template table<T>::emplace_uninitialized(*this, value);
_functions = functions::template table<T>::make();
}
/// The precondition is that *this is uninitialized (or destroyed).
void emplace_uninitialized(const any& other)
{
if (!other.empty())
{
other._functions.emplace_uninitialized(*this, other);
_functions = other._functions;
}
else
{
_id = {};
}
}
template <typename T>
any& assign(const T& value)
{
if (!try_assign_same(value))
{
// TODO: Cache allocated buffer and reuse.
destroy();
emplace_uninitialized(value);
}
return *this;
}
template <typename T>
bool try_assign_same(const T& value)
{
if (_id == TypeId<T>::value)
{
functions::template table<T>::assign(*this, value);
return true;
}
return false;
}
bool try_assign_same(const any& other)
{
if (_id == other._id)
{
if (!empty())
{
_functions.assign(*this, other);
}
return true;
}
return false;
}
void destroy()
{
if (!empty())
{
_functions.destroy(*this);
_id = {};
}
}
storage _storage;
functions _functions;
std::uint32_t _id;
};
template <typename T, template <typename> class TypeId, std::size_t Size>
inline T* any_cast(any<TypeId, Size>* x) BOND_NOEXCEPT
{
BOOST_ASSERT(x);
return x->template cast<T>();
}
template <typename T, template <typename> class TypeId, std::size_t Size>
inline const T* any_cast(const any<TypeId, Size>* x) BOND_NOEXCEPT
{
BOOST_ASSERT(x);
return x->template cast<T>();
}
} // namespace detail
} // namespace bond

Просмотреть файл

@ -18,16 +18,17 @@ namespace bond
typename Transform::writer_type::Pass0>::value>::type
> : true_type {};
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
inline bool DoublePassApply(const Transform& transform, const T& value)
{
typedef typename Transform::writer_type Writer;
typedef Serializer<Writer, Protocols> Serializer;
typename Writer::Pass0::Buffer output;
typename Writer::Pass0 pass0(output, transform.Serializer<Writer>::_output);
typename Writer::Pass0 pass0(output, transform.Serializer::_output);
Apply(transform.Rebind(pass0), value);
return transform.Serializer<Writer>::_output.WithPass0(pass0), Apply(transform, value);
Apply<Protocols>(transform.Rebind(pass0), value);
return transform.Serializer::_output.WithPass0(pass0), Apply<Protocols>(transform, value);
}
} // namespace detail

Просмотреть файл

@ -37,19 +37,10 @@ expected_depth
: std::integral_constant<uint16_t, 0xffff> {};
template <typename T> struct
expected_depth<bond::To<T> >
template <typename T, typename Protocols, typename Validator> struct
expected_depth<bond::To<T, Protocols, Validator> >
: hierarchy_depth<typename schema<T>::type> {};
template <typename Input, typename T = void, typename Enable = void> struct
is_reader
: false_type {};
template <typename Input, typename T> struct
is_reader<Input&, T, typename boost::enable_if<is_class<typename Input::Parser> >::type>
: true_type {};
template <typename Base, typename T>
inline Base& base_cast(T& obj)

Просмотреть файл

@ -29,13 +29,13 @@ auto ReadBlob(Reader& reader)
}
template <typename T, typename Writer>
template <typename Protocols, typename T, typename Writer>
void MarshalToBlob(const T& obj, Writer& writer)
{
auto output = CreateOutputBuffer(writer.GetBuffer());
CompactBinaryWriter<decltype(output)> cbw(output);
Marshal(obj, cbw);
Marshal<Protocols>(obj, cbw);
auto data = std::move(output).GetBuffer();
writer.Write(static_cast<uint32_t>(data.size()));

Просмотреть файл

@ -0,0 +1,120 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
/*
* This header provides a faster alternative to some of the facilities provided by boost::mpl.
*/
#pragma once
#include <boost/static_assert.hpp>
#include <initializer_list>
#include <type_traits>
namespace bond
{
namespace detail {namespace mpl
{
template <typename T> struct
identity
{
using type = T;
};
/// @brief Represents a type list.
template <typename... T> struct
list {};
/// @brief Appends the given list of types or a single pack of list<> to the end.
template <typename List, typename... T> struct
append;
template <typename List, typename... T>
using append_t = typename append<List, T...>::type;
template <typename List, typename... T> struct
append
: append<List, list<T...> > {};
template <typename... T, typename... U> struct
append<list<T...>, list<U...> >
: identity<list<T..., U...> > {};
/// @brief Filters the given type list with the provided predicate.
template <typename List, template <typename> class C> struct
filter;
template <typename List, template <typename> class C>
using filter_t = typename filter<List, C>::type;
template <template <typename> class C> struct
filter<list<>, C>
: identity<list<> > {};
template <typename T, typename... U, template <typename> class C> struct
filter<list<T, U...>, C>
: append< typename std::conditional<C<T>::value, list<T>, list<> >::type, filter_t<list<U...>, C> > {};
template <typename F, typename... T>
inline void apply(F&& f, const list<T...>&)
{
std::initializer_list<int>{ (f(identity<T>{}), 0)... };
}
template <typename F>
inline void apply(F&& /*f*/, const list<>&)
{}
template <typename List, typename F>
inline void apply(F&& f)
{
apply(std::forward<F>(f), List{});
}
template <typename F, typename T>
inline auto try_apply(F&& f, const list<T>&)
#ifdef BOND_NO_CXX14_RETURN_TYPE_DEDUCTION
-> decltype(std::forward<F>(f)(identity<T>{}))
#endif
{
return std::forward<F>(f)(identity<T>{});
}
template <typename F, typename T, typename U, typename... R>
inline auto try_apply(F&& f, const list<T, U, R...>&)
#ifdef BOND_NO_CXX14_RETURN_TYPE_DEDUCTION
-> decltype(f(identity<T>{}))
#endif
{
if (auto&& result = f(identity<T>{}))
{
return result;
}
return try_apply(std::forward<F>(f), list<U, R...>{});
}
template <typename List, typename F>
inline auto try_apply(F&& f)
#ifdef BOND_NO_CXX14_RETURN_TYPE_DEDUCTION
-> decltype(try_apply(std::forward<F>(f), List{}))
#endif
{
BOOST_STATIC_ASSERT(!std::is_same<List, list<> >::value);
return try_apply(std::forward<F>(f), List{});
}
}} // namespace mpl {namespace detail
} // namespace bond

Просмотреть файл

@ -8,13 +8,15 @@
#include <bond/stream/input_buffer.h>
#include <bond/stream/output_buffer.h>
#include <bond/core/traits.h>
#include <bond/core/null.h>
namespace bond
{
class RuntimeSchema;
template <typename Writer>
template <typename Writer, typename Protocols>
class Serializer;
namespace detail
@ -24,8 +26,7 @@ namespace detail
// It is used to dispatch to appropriate protocol at runtime.
template <typename T, typename Schema, typename Transform>
class _Parser
: public boost::static_visitor<bool>,
boost::noncopyable
: boost::noncopyable
{
public:
_Parser(const Transform& transform, const Schema& schema)
@ -51,11 +52,11 @@ public:
return false;
}
template <typename Reader, typename Writer>
template <typename Reader, typename Writer, typename Protocols>
static
typename boost::enable_if_c<is_protocol_same<Reader, Writer>::value
&& protocol_has_multiple_versions<Reader>::value, bool>::type
Apply(const Serializer<Writer>& transform, Reader& reader, const Schema& schema, bool base)
Apply(const Serializer<Writer, Protocols>& transform, Reader& reader, const Schema& schema, bool base)
{
if (is_protocol_version_same(reader, transform._output))
return FastPassThrough(reader, transform._output, schema);
@ -63,11 +64,11 @@ public:
return typename Reader::Parser(reader, base).Apply(transform, schema);
}
template <typename Reader, typename Writer>
template <typename Reader, typename Writer, typename Protocols>
static
typename boost::enable_if_c<is_protocol_same<Reader, Writer>::value
&& !protocol_has_multiple_versions<Reader>::value, bool>::type
Apply(const Serializer<Writer>& transform, Reader& reader, const Schema& schema, bool base)
Apply(const Serializer<Writer, Protocols>& transform, Reader& reader, const Schema& schema, bool base)
{
BOOST_VERIFY(!base);
// Triggering the following assert means that bond::enable_protocol_versions trait is
@ -154,72 +155,96 @@ protected:
template <typename Reader, typename T>
inline void Skip(Reader& reader, const T& bonded)
inline void Skip(Reader& reader, const bonded<T, Reader&>& bonded)
{
reader.Skip(bonded);
}
template <typename T, template <typename BufferT, typename MarshaledBondedProtocolsT> class Reader, typename Buffer, typename MarshaledBondedProtocols>
inline void Skip(const bonded<T, Reader<Buffer, MarshaledBondedProtocols>&>& bonded)
{
// Skip the structure field-by-field by applying Null transform
Apply<MarshaledBondedProtocols>(Null(), bonded);
}
template <typename Reader, typename T>
BOND_NO_INLINE void Skip(Reader& reader, const T& bonded, const std::nothrow_t&)
BOND_NO_INLINE void Skip(Reader& reader, const bonded<T, Reader&>& bonded, const std::nothrow_t&)
{
try
{
reader.Skip(bonded);
Skip(reader, bonded);
}
catch(...)
{
}
{}
}
template <typename T>
inline void Skip(ProtocolReader& /*reader*/, const T& /*bonded*/)
inline void Skip(ProtocolReader& /*reader*/, const bonded<T>& /*bonded*/)
{
// Not skipping for outer structures
}
template <typename T>
inline void Skip(ProtocolReader& /*reader*/, const T& /*bonded*/, const std::nothrow_t&)
inline void Skip(ProtocolReader& /*reader*/, const bonded<T>& /*bonded*/, const std::nothrow_t&)
{
// Not skipping for outer structures
}
template <typename T, typename Transform, typename Reader, typename Schema>
template <typename T, typename Protocols, typename Transform, typename Reader, typename Schema>
inline bool Parse(const Transform& transform, Reader& reader, const Schema& schema, const RuntimeSchema* runtime_schema, bool base)
{
BOOST_VERIFY(!runtime_schema);
return Parser<T, Schema, Transform>::Apply(transform, reader, schema, base);
}
template <typename T, typename Transform, typename Schema>
template <typename T, typename Protocols, typename Transform, typename Schema>
inline bool Parse(const Transform& transform, ProtocolReader reader, const Schema& schema, const RuntimeSchema* runtime_schema, bool base)
{
BOOST_VERIFY(!base);
boost::optional<bool> result;
if (runtime_schema)
{
// Use named variable to avoid gcc silently copying objects (which
// causes build break, because Parser<> is non-copyable).
Parser<void, RuntimeSchema, Transform> parser(transform, *runtime_schema);
return boost::apply_visitor(parser, reader.value);
result = reader.template Visit<Protocols
#if defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) || defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
, bool
#endif
>(parser);
}
else
{
// Use named variable to avoid gcc silently copying objects (which
// causes build break, because Parser<> is non-copyable).
Parser<T, Schema, Transform> parser(transform, schema);
return boost::apply_visitor(parser, reader.value);
result = reader.template Visit<Protocols
#if defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) || defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
, bool
#endif
>(parser);
}
if (result)
{
return result.get();
}
UnknownProtocolException();
}
// Visitor which updates in-situ bonded<T> payload by merging it with an object.
template <typename T, typename Buffer>
class InsituMerge
: public boost::static_visitor<>,
boost::noncopyable
: boost::noncopyable
{
public:
InsituMerge(const T& var, ProtocolReader& reader)
@ -261,10 +286,17 @@ private:
};
template <typename Buffer = OutputBuffer, typename T>
template <typename Protocols, typename Buffer = OutputBuffer, typename T>
inline void Merge(const T& var, ProtocolReader& reader)
{
boost::apply_visitor(InsituMerge<T, Buffer>(var, reader), reader.value);
if (!reader.template Visit<Protocols
#if defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) || defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
, void
#endif
>(InsituMerge<T, Buffer>(var, reader)))
{
UnknownProtocolException();
}
}

Просмотреть файл

@ -3,12 +3,15 @@
#pragma once
#include <bond/core/bond_fwd.h>
#include <bond/core/bond_const_enum.h>
#include "nonassignable.h"
#include <type_traits>
namespace bond
{
struct Metadata;
// Used to get qualified name of enum using generated GetTypeName
struct qualified_name_tag
{};
@ -74,17 +77,17 @@ struct ModifyingTransform
template <typename T, typename Unused = void> struct
is_serializing_transform
: is_base_of<SerializingTransform, T> {};
: std::is_base_of<SerializingTransform, T> {};
template <typename T, typename Unused = void> struct
is_deserializing_transform
: is_base_of<DeserializingTransform, T> {};
: std::is_base_of<DeserializingTransform, T> {};
template <typename T, typename Unused = void> struct
is_modifying_transform
: is_base_of<ModifyingTransform, T> {};
: std::is_base_of<ModifyingTransform, T> {};
} // namespace bond

Просмотреть файл

@ -6,6 +6,41 @@
namespace bond
{
template <typename Protocols, typename X, typename Key, typename T>
typename boost::enable_if<is_map_key_matching<Key, X> >::type
inline DeserializeMapElements(X& var, const Key& key, const T& element, uint32_t size);
template <typename Protocols, typename X, typename Key, typename T>
typename boost::disable_if<is_map_key_matching<Key, X> >::type
inline DeserializeMapElements(X&, const Key& key, const T& element, uint32_t size);
template <typename Protocols, typename Transform, typename Key, typename T>
inline void DeserializeMapElements(const Transform& transform, const Key& key, const T& element, uint32_t size);
template <typename Protocols, typename X, typename T>
typename boost::enable_if_c<is_list_container<X>::value
&& is_element_matching<T, X>::value>::type
inline DeserializeElements(X& var, const T& element, uint32_t size);
template <typename Protocols, typename X, typename Allocator, bool useValue, typename T>
typename boost::enable_if<is_matching<T, X> >::type
inline DeserializeElements(nullable<X, Allocator, useValue>& var, const T& element, uint32_t size);
template <typename Protocols, typename Reader>
inline void DeserializeElements(blob& var, const value<blob::value_type, Reader&>& element, uint32_t size);
template <typename Protocols, typename X, typename T>
typename boost::enable_if_c<is_set_container<X>::value
&& is_element_matching<T, X>::value>::type
inline DeserializeElements(X& var, const T& element, uint32_t size);
template <typename Protocols, typename X, typename T>
typename boost::disable_if<is_element_matching<T, X> >::type
inline DeserializeElements(X&, const T& element, uint32_t size);
template <typename Protocols, typename Transform, typename T>
inline void DeserializeElements(const Transform& transform, const T& element, uint32_t size);
namespace detail
{
@ -115,7 +150,7 @@ inline bool BasicTypeField(uint16_t id, const Metadata& metadata, BondDataType t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
inline void BasicTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
BOOST_STATIC_ASSERT(!is_container<T>::value);
@ -123,43 +158,43 @@ inline void BasicTypeContainer(T& var, BondDataType type, Reader& input, uint32_
switch (type)
{
case bond::BT_BOOL:
return DeserializeElements(var, value<bool, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<bool, Reader&>(input, false), size);
case bond::BT_UINT8:
return DeserializeElements(var, value<uint8_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint8_t, Reader&>(input, false), size);
case bond::BT_UINT16:
return DeserializeElements(var, value<uint16_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint16_t, Reader&>(input, false), size);
case bond::BT_UINT32:
return DeserializeElements(var, value<uint32_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint32_t, Reader&>(input, false), size);
case bond::BT_UINT64:
return DeserializeElements(var, value<uint64_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint64_t, Reader&>(input, false), size);
case bond::BT_FLOAT:
return DeserializeElements(var, value<float, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<float, Reader&>(input, false), size);
case bond::BT_DOUBLE:
return DeserializeElements(var, value<double, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<double, Reader&>(input, false), size);
case bond::BT_STRING:
return DeserializeElements(var, value<std::string, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<std::string, Reader&>(input, false), size);
case bond::BT_WSTRING:
return DeserializeElements(var, value<std::wstring, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<std::wstring, Reader&>(input, false), size);
case bond::BT_INT8:
return DeserializeElements(var, value<int8_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int8_t, Reader&>(input, false), size);
case bond::BT_INT16:
return DeserializeElements(var, value<int16_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int16_t, Reader&>(input, false), size);
case bond::BT_INT32:
return DeserializeElements(var, value<int32_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int32_t, Reader&>(input, false), size);
case bond::BT_INT64:
return DeserializeElements(var, value<int64_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int64_t, Reader&>(input, false), size);
default:
BOOST_ASSERT(false);
@ -170,13 +205,13 @@ inline void BasicTypeContainer(T& var, BondDataType type, Reader& input, uint32_
// MatchingTypeContainer function are manually expended versions of BasicTypeContainer
// using the type information about destination container. This helps with compilation speed.
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_type_alias<typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
if (type == get_type_id<typename element_type<T>::type>::value)
{
DeserializeElements(var, value<typename element_type<T>::type, Reader&>(input, false), size);
DeserializeElements<Protocols>(var, value<typename element_type<T>::type, Reader&>(input, false), size);
}
else
{
@ -188,14 +223,14 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_same<bool, typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_BOOL:
return DeserializeElements(var, value<bool, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<bool, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -207,14 +242,14 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_string<typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_STRING:
return DeserializeElements(var, value<std::string, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<std::string, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -226,14 +261,14 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_wstring<typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_WSTRING:
return DeserializeElements(var, value<std::wstring, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<std::wstring, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -245,17 +280,17 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_floating_point<typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_FLOAT:
return DeserializeElements(var, value<float, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<float, Reader&>(input, false), size);
case bond::BT_DOUBLE:
return DeserializeElements(var, value<double, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<double, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -267,23 +302,23 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_matching<uint8_t, typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_UINT8:
return DeserializeElements(var, value<uint8_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint8_t, Reader&>(input, false), size);
case bond::BT_UINT16:
return DeserializeElements(var, value<uint16_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint16_t, Reader&>(input, false), size);
case bond::BT_UINT32:
return DeserializeElements(var, value<uint32_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint32_t, Reader&>(input, false), size);
case bond::BT_UINT64:
return DeserializeElements(var, value<uint64_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<uint64_t, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -295,23 +330,23 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_matching<int8_t, typename element_type<T>::type> >::type
inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t size)
{
switch (type)
{
case bond::BT_INT8:
return DeserializeElements(var, value<int8_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int8_t, Reader&>(input, false), size);
case bond::BT_INT16:
return DeserializeElements(var, value<int16_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int16_t, Reader&>(input, false), size);
case bond::BT_INT32:
return DeserializeElements(var, value<int32_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int32_t, Reader&>(input, false), size);
case bond::BT_INT64:
return DeserializeElements(var, value<int64_t, Reader&>(input, false), size);
return DeserializeElements<Protocols>(var, value<int64_t, Reader&>(input, false), size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type>(type));
@ -322,16 +357,17 @@ inline MatchingTypeContainer(T& var, BondDataType type, Reader& input, uint32_t
}
}
// MatchingMapByKey function are manually expended versions of MapByKey using the type
// information about destination container. This helps with compilation speed.
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_type_alias<typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
if (keyType == get_type_id<typename element_type<T>::type::first_type>::value)
{
return DeserializeMapElements(var, value<typename element_type<T>::type::first_type, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<typename element_type<T>::type::first_type, Reader&>(input, false), element, size);
}
else
{
@ -346,14 +382,14 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_same<bool, typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_BOOL:
return DeserializeMapElements(var, value<bool, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<bool, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -368,14 +404,14 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_string<typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_STRING:
return DeserializeMapElements(var, value<std::string, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<std::string, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -390,14 +426,14 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_wstring<typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_WSTRING:
return DeserializeMapElements(var, value<std::wstring, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<std::wstring, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -412,17 +448,17 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_floating_point<typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_FLOAT:
return DeserializeMapElements(var, value<float, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<float, Reader&>(input, false), element, size);
case bond::BT_DOUBLE:
return DeserializeMapElements(var, value<double, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<double, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -437,23 +473,23 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_matching<uint8_t, typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_UINT8:
return DeserializeMapElements(var, value<uint8_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint8_t, Reader&>(input, false), element, size);
case bond::BT_UINT16:
return DeserializeMapElements(var, value<uint16_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint16_t, Reader&>(input, false), element, size);
case bond::BT_UINT32:
return DeserializeMapElements(var, value<uint32_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint32_t, Reader&>(input, false), element, size);
case bond::BT_UINT64:
return DeserializeMapElements(var, value<uint64_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint64_t, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -468,23 +504,23 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_matching<int8_t, typename element_type<T>::type::first_type> >::type
inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_INT8:
return DeserializeMapElements(var, value<int8_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int8_t, Reader&>(input, false), element, size);
case bond::BT_INT16:
return DeserializeMapElements(var, value<int16_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int16_t, Reader&>(input, false), element, size);
case bond::BT_INT32:
return DeserializeMapElements(var, value<int32_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int32_t, Reader&>(input, false), element, size);
case bond::BT_INT64:
return DeserializeMapElements(var, value<int64_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int64_t, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::first_type>(keyType));
@ -500,50 +536,50 @@ inline MatchingMapByKey(T& var, BondDataType keyType, const E& element, Reader&
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::disable_if<is_map_container<T> >::type
inline MapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
switch (keyType)
{
case bond::BT_BOOL:
return DeserializeMapElements(var, value<bool, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<bool, Reader&>(input, false), element, size);
case bond::BT_UINT8:
return DeserializeMapElements(var, value<uint8_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint8_t, Reader&>(input, false), element, size);
case bond::BT_UINT16:
return DeserializeMapElements(var, value<uint16_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint16_t, Reader&>(input, false), element, size);
case bond::BT_UINT32:
return DeserializeMapElements(var, value<uint32_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint32_t, Reader&>(input, false), element, size);
case bond::BT_UINT64:
return DeserializeMapElements(var, value<uint64_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<uint64_t, Reader&>(input, false), element, size);
case bond::BT_FLOAT:
return DeserializeMapElements(var, value<float, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<float, Reader&>(input, false), element, size);
case bond::BT_DOUBLE:
return DeserializeMapElements(var, value<double, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<double, Reader&>(input, false), element, size);
case bond::BT_STRING:
return DeserializeMapElements(var, value<std::string, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<std::string, Reader&>(input, false), element, size);
case bond::BT_WSTRING:
return DeserializeMapElements(var, value<std::wstring, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<std::wstring, Reader&>(input, false), element, size);
case bond::BT_INT8:
return DeserializeMapElements(var, value<int8_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int8_t, Reader&>(input, false), element, size);
case bond::BT_INT16:
return DeserializeMapElements(var, value<int16_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int16_t, Reader&>(input, false), element, size);
case bond::BT_INT32:
return DeserializeMapElements(var, value<int32_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int32_t, Reader&>(input, false), element, size);
case bond::BT_INT64:
return DeserializeMapElements(var, value<int64_t, Reader&>(input, false), element, size);
return DeserializeMapElements<Protocols>(var, value<int64_t, Reader&>(input, false), element, size);
default:
BOOST_ASSERT(false);
@ -552,15 +588,15 @@ inline MapByKey(T& var, BondDataType keyType, const E& element, Reader& input, u
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::enable_if<is_map_element_matching<E, T> >::type
inline MapByKey(T& var, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
return MatchingMapByKey(var, keyType, element, input, size);
return MatchingMapByKey<Protocols>(var, keyType, element, input, size);
}
template <typename T, typename E, typename Reader>
template <typename Protocols, typename T, typename E, typename Reader>
typename boost::disable_if_c<!is_map_container<T>::value || is_map_element_matching<E, T>::value>::type
inline MapByKey(T&, BondDataType keyType, const E& element, Reader& input, uint32_t size)
{
@ -572,49 +608,49 @@ inline MapByKey(T&, BondDataType keyType, const E& element, Reader& input, uint3
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
inline void MapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_BOOL:
return MapByKey(var, keyType, value<bool, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<bool, Reader&>(input, false), input, size);
case bond::BT_UINT8:
return MapByKey(var, keyType, value<uint8_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint8_t, Reader&>(input, false), input, size);
case bond::BT_UINT16:
return MapByKey(var, keyType, value<uint16_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint16_t, Reader&>(input, false), input, size);
case bond::BT_UINT32:
return MapByKey(var, keyType, value<uint32_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint32_t, Reader&>(input, false), input, size);
case bond::BT_UINT64:
return MapByKey(var, keyType, value<uint64_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint64_t, Reader&>(input, false), input, size);
case bond::BT_FLOAT:
return MapByKey(var, keyType, value<float, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<float, Reader&>(input, false), input, size);
case bond::BT_DOUBLE:
return MapByKey(var, keyType, value<double, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<double, Reader&>(input, false), input, size);
case bond::BT_STRING:
return MapByKey(var, keyType, value<std::string, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<std::string, Reader&>(input, false), input, size);
case bond::BT_WSTRING:
return MapByKey(var, keyType, value<std::wstring, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<std::wstring, Reader&>(input, false), input, size);
case bond::BT_INT8:
return MapByKey(var, keyType, value<int8_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int8_t, Reader&>(input, false), input, size);
case bond::BT_INT16:
return MapByKey(var, keyType, value<int16_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int16_t, Reader&>(input, false), input, size);
case bond::BT_INT32:
return MapByKey(var, keyType, value<int32_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int32_t, Reader&>(input, false), input, size);
case bond::BT_INT64:
return MapByKey(var, keyType, value<int64_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int64_t, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(false);
@ -626,13 +662,13 @@ inline void MapByElement(T& var, BondDataType keyType, BondDataType elementType,
// MatchingMapByElement function are manually expended versions of MapByElement using
// the type information about destination container. This helps with compilation speed.
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_type_alias<typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
if (elementType == get_type_id<typename element_type<T>::type::second_type>::value)
{
MapByKey(var, keyType, value<typename element_type<T>::type::second_type, Reader&>(input, false), input, size);
MapByKey<Protocols>(var, keyType, value<typename element_type<T>::type::second_type, Reader&>(input, false), input, size);
}
else
{
@ -647,14 +683,14 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_same<bool, typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_BOOL:
return MapByKey(var, keyType, value<bool, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<bool, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));
@ -669,14 +705,14 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_string<typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_STRING:
return MapByKey(var, keyType, value<std::string, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<std::string, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));
@ -691,14 +727,14 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_wstring<typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_WSTRING:
return MapByKey(var, keyType, value<std::wstring, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<std::wstring, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));
@ -713,17 +749,17 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_floating_point<typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_FLOAT:
return MapByKey(var, keyType, value<float, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<float, Reader&>(input, false), input, size);
case bond::BT_DOUBLE:
return MapByKey(var, keyType, value<double, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<double, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));
@ -738,23 +774,23 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_matching<uint8_t, typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_UINT8:
return MapByKey(var, keyType, value<uint8_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint8_t, Reader&>(input, false), input, size);
case bond::BT_UINT16:
return MapByKey(var, keyType, value<uint16_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint16_t, Reader&>(input, false), input, size);
case bond::BT_UINT32:
return MapByKey(var, keyType, value<uint32_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint32_t, Reader&>(input, false), input, size);
case bond::BT_UINT64:
return MapByKey(var, keyType, value<uint64_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<uint64_t, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));
@ -769,23 +805,23 @@ inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementTy
}
template <typename T, typename Reader>
template <typename Protocols, typename T, typename Reader>
typename boost::enable_if<is_matching<int8_t, typename element_type<T>::type::second_type> >::type
inline MatchingMapByElement(T& var, BondDataType keyType, BondDataType elementType, Reader& input, uint32_t size)
{
switch (elementType)
{
case bond::BT_INT8:
return MapByKey(var, keyType, value<int8_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int8_t, Reader&>(input, false), input, size);
case bond::BT_INT16:
return MapByKey(var, keyType, value<int16_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int16_t, Reader&>(input, false), input, size);
case bond::BT_INT32:
return MapByKey(var, keyType, value<int32_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int32_t, Reader&>(input, false), input, size);
case bond::BT_INT64:
return MapByKey(var, keyType, value<int64_t, Reader&>(input, false), input, size);
return MapByKey<Protocols>(var, keyType, value<int64_t, Reader&>(input, false), input, size);
default:
BOOST_ASSERT(!IsMatching<typename element_type<T>::type::second_type>(elementType));

Просмотреть файл

@ -207,6 +207,7 @@ inline void ValidateStruct(const RuntimeSchema& src,
// Checks if payload contains unknown fields
template <typename Protocols>
class SchemaValidator
: public DeserializingTransform
{
@ -271,14 +272,14 @@ private:
typename boost::disable_if<is_basic_type<T>, bool>::type
Recurse(const value<T, Reader>& value) const
{
Apply(*this, value);
Apply<Protocols>(*this, value);
return false;
}
template <typename T, typename Reader>
bool Recurse(const bonded<T, Reader>& value) const
{
return Apply(*this, value);
return Apply<Protocols>(*this, value);
}
};

Просмотреть файл

@ -0,0 +1,125 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#pragma once
#include "mpl.h"
#include <boost/optional.hpp>
#include <type_traits>
namespace bond
{
namespace detail
{
#if !defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) && !defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
template <typename T, typename Visitor, typename Any>
inline typename boost::disable_if<std::is_void<std::result_of_t<Visitor(T&)> >, boost::optional<std::result_of_t<Visitor(T&)> > >::type
try_visit_any(Visitor&& visitor, Any& x)
{
if (auto value = any_cast<T>(&x))
{
return std::forward<Visitor>(visitor)(*value);
}
return {};
}
template <typename T, typename Visitor, typename Any>
inline typename boost::enable_if<std::is_void<std::result_of_t<Visitor(T&)> >, bool>::type
try_visit_any(Visitor&& visitor, Any& x)
{
if (auto value = any_cast<T>(&x))
{
std::forward<Visitor>(visitor)(*value);
return true;
}
return false;
}
template <typename List, typename Visitor, typename Any>
inline auto visit_any(Visitor&& visitor, Any& x)
{
return mpl::try_apply<List>(
[&](auto identity)
{
(void)identity;
return try_visit_any<typename decltype(identity)::type>(std::forward<Visitor>(visitor), x);
});
}
#else
template <typename Result, typename Visitor, typename Any>
struct try_visit_any
{
try_visit_any(Visitor& visitor, Any& x)
: _visitor(visitor),
_x(x)
{}
try_visit_any& operator=(const try_visit_any& other) = delete;
template <typename T, typename R = Result>
typename boost::disable_if<std::is_void<R>, boost::optional<Result> >::type
operator()(const mpl::identity<T>&) const
{
if (auto value = any_cast<T>(&_x))
{
return _visitor(*value);
}
return {};
}
template <typename T, typename R = Result>
typename boost::enable_if<std::is_void<R>, bool>::type
operator()(const mpl::identity<T>&) const
{
if (auto value = any_cast<T>(&_x))
{
_visitor(*value);
return true;
}
return false;
}
Visitor& _visitor;
Any& _x;
};
template <typename T> struct
visitor_result
{
using type = boost::optional<T>;
};
template <> struct
visitor_result<void>
{
using type = bool;
};
template <typename Result, typename Visitor, typename Any, typename T, typename... U>
inline typename visitor_result<Result>::type visit_any(Visitor&& visitor, Any& x, const mpl::list<T, U...>&)
{
return mpl::try_apply<mpl::list<T, U...> >(try_visit_any<Result, Visitor, Any>(visitor, x));
}
template <typename List, typename Result, typename Visitor, typename Any>
inline typename visitor_result<Result>::type visit_any(Visitor&& visitor, Any& x)
{
return visit_any<Result>(std::forward<Visitor>(visitor), x, List{});
}
#endif
} // namespace detail
} // namespace bond

Просмотреть файл

@ -14,18 +14,18 @@ namespace bond
{
template <typename T, typename Writer>
template <typename T, typename Writer, typename Protocols = BuiltInProtocols>
class Merger
: public Serializer<Writer>
{
public:
typedef T FastPathType;
using Serializer<Writer>::Base;
using Serializer<Writer>::Field;
using Serializer<Writer>::Write;
using Serializer<Writer>::OmittedField;
using Serializer<Writer>::Container;
using Serializer<Writer, Protocols>::Base;
using Serializer<Writer, Protocols>::Field;
using Serializer<Writer, Protocols>::Write;
using Serializer<Writer, Protocols>::OmittedField;
using Serializer<Writer, Protocols>::Container;
Merger(const T& var, Writer& output, bool base = false)
: Serializer<Writer>(output, base),
@ -33,16 +33,16 @@ public:
{}
template <typename Pass0>
Merger<T, Pass0> Rebind(Pass0& pass0) const
Merger<T, Pass0, Protocols> Rebind(Pass0& pass0) const
{
return Merger<T, Pass0>(_var, pass0);
return Merger<T, Pass0, Protocols>(_var, pass0);
}
template <typename X, typename Reader>
typename boost::enable_if<has_schema<X>, bool>::type
Base(const bonded<X, Reader>& value) const
{
return Apply(Merger<typename schema<T>::type::base, Writer>(_var, _output, true), value);
return Apply<Protocols>(Merger<typename schema<T>::type::base, Writer, Protocols>(_var, _output, true), value);
}
@ -100,14 +100,14 @@ public:
protected:
using Serializer<Writer>::_output;
using Serializer<Writer, Protocols>::_output;
private:
template <typename U, typename X>
void Merge(const U& var, const X& value) const
{
Apply(Merger<U, Writer>(var, _output), value);
Apply<Protocols>(Merger<U, Writer, Protocols>(var, _output), value);
}
@ -138,7 +138,7 @@ private:
while (size--)
{
key.Deserialize(k);
key.template Deserialize<Protocols>(k);
Write(k);

Просмотреть файл

@ -27,6 +27,12 @@ public:
return Apply(*this, base);
}
template <typename T, template <typename BufferT, typename MarshaledBondedProtocolsT> class Reader, typename Buffer, typename MarshaledBondedProtocols>
bool Base(const bonded<T, Reader<Buffer, MarshaledBondedProtocols>&>& base) const
{
return Apply<MarshaledBondedProtocols>(*this, base);
}
template <typename T>
bool Field(uint16_t, const Metadata&, const T&) const
{

Просмотреть файл

@ -137,7 +137,7 @@ private:
template <typename T, typename Transform>
typename boost::enable_if_c<detail::is_reader<Input>::value && !is_nested_field<T>::value
typename boost::enable_if_c<is_reader<Input>::value && !is_nested_field<T>::value
&& !is_fast_path_field<T, Transform>::value, bool>::type
NextField(const T&, const Transform& transform)
{
@ -146,7 +146,7 @@ private:
template <typename T, typename Transform>
typename boost::enable_if_c<detail::is_reader<Input>::value && !is_nested_field<T>::value
typename boost::enable_if_c<is_reader<Input>::value && !is_nested_field<T>::value
&& is_fast_path_field<T, Transform>::value, bool>::type
NextField(const T& field, const Transform& transform)
{
@ -155,7 +155,7 @@ private:
template <typename T, typename Transform>
typename boost::enable_if_c<detail::is_reader<Input>::value && is_nested_field<T>::value
typename boost::enable_if_c<is_reader<Input>::value && is_nested_field<T>::value
&& !is_fast_path_field<T, Transform>::value, bool>::type
NextField(const T&, const Transform& transform)
{
@ -164,7 +164,7 @@ private:
template <typename T, typename Transform>
typename boost::enable_if_c<detail::is_reader<Input>::value && is_nested_field<T>::value
typename boost::enable_if_c<is_reader<Input>::value && is_nested_field<T>::value
&& is_fast_path_field<T, Transform>::value, bool>::type
NextField(const T& field, const Transform& transform)
{
@ -173,7 +173,7 @@ private:
template <typename T, typename Transform>
typename boost::disable_if<detail::is_reader<Input, T>, bool>::type
typename boost::disable_if<is_reader<Input, T>, bool>::type
NextField(const T&, const Transform& transform)
{
return transform.Field(T::id, T::metadata, T::GetVariable(_input));
@ -498,8 +498,8 @@ private:
}
template <typename T>
bool UnknownField(uint16_t, BondDataType type, const To<T>&)
template <typename T, typename Protocols, typename Validator>
bool UnknownField(uint16_t, BondDataType type, const To<T, Protocols, Validator>&)
{
_input.Skip(type);
return false;

Просмотреть файл

@ -3,22 +3,22 @@
#pragma once
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>
#include <boost/ref.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/mpl/contains.hpp>
#include "traits.h"
#include "customize.h"
#include "detail/any.h"
#include "detail/mpl.h"
#include "detail/odr.h"
#include "detail/visit_any.h"
#include <bond/stream/input_buffer.h>
#include <bond/protocol/simple_binary.h>
#include <bond/protocol/compact_binary.h>
#include <bond/protocol/fast_binary.h>
#include <bond/protocol/simple_json_reader.h>
#include <boost/make_shared.hpp>
#include <boost/optional.hpp>
#include <boost/ref.hpp>
#if !defined(BOND_COMPACT_BINARY_PROTOCOL) \
&& !defined(BOND_SIMPLE_BINARY_PROTOCOL) \
&& !defined(BOND_FAST_BINARY_PROTOCOL) \
@ -41,8 +41,8 @@ is_protocol_enabled<CompactBinaryReader<Buffer> >
#endif
#ifdef BOND_SIMPLE_BINARY_PROTOCOL
template <typename Buffer> struct
is_protocol_enabled<SimpleBinaryReader<Buffer> >
template <typename Buffer, typename MarshaledBondedProtocols> struct
is_protocol_enabled<SimpleBinaryReader<Buffer, MarshaledBondedProtocols> >
: true_type {};
#endif
@ -106,10 +106,58 @@ uses_marshaled_bonded
: uses_static_parser<Reader> {};
template <typename... T>
struct Protocols
{
private:
template <typename Buffer>
struct FilterBufferHelper;
public:
using type = detail::mpl::list<T...>;
template <typename... U>
using Append = typename Protocols<detail::mpl::append_t<type, U...> >::type;
using FilterEnabled = typename Protocols<detail::mpl::filter_t<type, is_protocol_enabled> >::type;
template <typename Buffer>
using FilterBuffer = typename FilterBufferHelper<Buffer>::type;
private:
template <typename Buffer>
struct FilterBufferHelper
{
template <typename U>
using check_buffer = std::is_same<typename std::remove_reference<typename U::Buffer>::type, Buffer>;
using type = typename Protocols<detail::mpl::filter_t<typename FilterEnabled::type, check_buffer> >::type;
};
};
template <typename... T>
struct Protocols<detail::mpl::list<T...> >
{
using type = Protocols<T...>;
};
// Deriving from Protocols<> instead of using an alias to avoid
// binary size increase due to much longer type/function names on VC.
struct BuiltInProtocols
: Protocols<
CompactBinaryReader<InputBuffer>,
SimpleBinaryReader<InputBuffer>,
FastBinaryReader<InputBuffer>,
SimpleJsonReader<InputBuffer> > {};
struct ValueReader
{
// Constructors that explicitly declared noexcept are needed for
// boost::variant to use optimized code path.
BOOST_STATIC_CONSTEXPR uint16_t magic = 0x5256 /*VR*/;
using Buffer = void;
ValueReader() BOND_NOEXCEPT
: pointer(NULL)
{}
@ -147,85 +195,82 @@ struct ValueReader
};
using boost::mpl::_;
BOND_DEFINE_BUFFER_MAGIC(ValueReader::Buffer, 0);
struct Protocols
namespace detail
{
typedef boost::mpl::list<
CompactBinaryReader<InputBuffer>,
SimpleBinaryReader<InputBuffer>,
FastBinaryReader<InputBuffer>,
SimpleJsonReader<InputBuffer>
>::type built_in;
#if !defined(_MSC_VER) || _MSC_VER >= 1900
typedef customize<protocols>::modify<built_in>::type all;
// Avoid std::max due to a bug in Visual C++ 2017.
template <std::size_t V0, std::size_t V1>
struct max_of
: std::integral_constant<std::size_t, (V0 < V1 ? V1 : V0)> {};
typedef boost::mpl::filter_view<all, is_protocol_enabled<_> >::type type;
template <typename List> struct
max_size;
typedef boost::mpl::begin<type>::type begin;
template <> struct
max_size<detail::mpl::list<> >
: std::integral_constant<std::size_t, 0> {};
typedef boost::mpl::end<type>::type end;
};
template <typename T, typename... U> struct
max_size<detail::mpl::list<T, U...> >
: max_of<sizeof(T), max_size<detail::mpl::list<U...> >::value> {};
using protocol_max_size = max_size<BuiltInProtocols::Append<ValueReader>::type>;
#else // !defined(_MSC_VER) || _MSC_VER >= 1900
// Use hard-coded 128 byte storage on VC12 as a compiler crash workaround.
using protocol_max_size = std::integral_constant<std::size_t, 128>;
#endif
} // namespace detail
template <typename InputBuffer>
struct FilteredProtocols
class ProtocolReader
{
private:
template <typename Reader, typename Enable = void> struct
check_buffer
: std::false_type {};
template <typename Reader> struct
check_buffer<Reader, typename boost::enable_if<std::is_same<typename Reader::Buffer, InputBuffer> >::type>
: std::true_type {};
public:
typedef typename boost::mpl::filter_view<Protocols::type, check_buffer<_> >::type type;
using Parser = void;
using Writer = void;
typedef typename boost::mpl::begin<type>::type begin;
typedef typename boost::mpl::end<type>::type end;
};
struct ProtocolReader
{
typedef void Parser;
typedef void Writer;
ProtocolReader()
: value()
{
// Validate that all compilation units in a program use the same set of protocols.
(void)one_definition<Protocols, Protocols::all>::value;
}
ProtocolReader(const ValueReader& x)
: value(x)
ProtocolReader(const ValueReader& reader = {})
: _value(reader)
{}
template <typename Reader, typename boost::enable_if<boost::mpl::contains<Protocols::all, Reader> >::type* = nullptr>
template <typename Reader, typename boost::enable_if<is_reader<Reader> >::type* = nullptr>
ProtocolReader(const Reader& reader)
: value(reader)
{}
ProtocolReader(const ProtocolReader& that)
: value(that.value)
: _value(reader)
{}
bool operator==(const ProtocolReader& rhs) const
bool operator==(const ProtocolReader& rhs) const
{
return value == rhs.value;
return _value == rhs._value;
}
boost::make_variant_over<
boost::mpl::insert_range<
boost::mpl::list<ValueReader>::type,
boost::mpl::end<boost::mpl::list<ValueReader>::type>::type,
Protocols::all
>::type
>::type value;
#if !defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) && !defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
template <typename Protocols, typename Visitor>
auto Visit(Visitor&& visitor)
#else
template <typename Protocols, typename Result, typename Visitor>
typename detail::visitor_result<Result>::type Visit(Visitor&& visitor)
#endif
{
return detail::visit_any<typename Protocols::template Append<ValueReader>::type
#if defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) || defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
, Result
#endif
>(std::forward<Visitor>(visitor), _value);
}
private:
template <typename Reader> struct
reader_id
: std::integral_constant<uint32_t, Reader::magic | (buffer_magic<typename Reader::Buffer>::value << 16)> {};
detail::any<reader_id, detail::protocol_max_size::value> _value;
};

Просмотреть файл

@ -65,17 +65,17 @@ inline BondDataType RuntimeSchema::GetTypeId() const
}
template <typename Writer>
template <typename Protocols = BuiltInProtocols, typename Writer>
inline void Serialize(const RuntimeSchema& schema, Writer& output)
{
Apply(SerializeTo(output), schema.GetSchema());
Apply<Protocols>(SerializeTo<Protocols>(output), schema.GetSchema());
}
template <typename Writer>
template <typename Protocols = BuiltInProtocols, typename Writer>
inline void Marshal(const RuntimeSchema& schema, Writer& output)
{
Apply(MarshalTo(output), schema.GetSchema());
Apply<Protocols>(MarshalTo<Protocols>(output), schema.GetSchema());
}
class InitSchemaDef;

Просмотреть файл

@ -8,6 +8,11 @@
#include "runtime_schema.h"
#include "exception.h"
#ifdef BOND_NO_CXX14_GENERIC_LAMBDAS
#include <functional>
#endif
namespace bond
{
namespace detail
@ -15,196 +20,212 @@ namespace detail
// Overload of Apply used to extract bonded<T> from marshaled payload
template <typename T, typename U, typename Reader>
template <typename Protocols, typename T, typename U, typename Reader>
inline bool
Apply(const boost::reference_wrapper<bonded<T> >& ref, const bonded<U, Reader>& value)
{
value.Deserialize(ref.get());
value.template Deserialize<Protocols>(ref.get());
return false;
}
// Select protocol and apply transform using compile-time schema
template <typename T, typename Buffer, typename Transform, typename EndIter>
inline std::pair<ProtocolType, bool> NextProtocol(
const EndIter&,
const EndIter&,
Buffer&,
const Transform&)
template <typename Protocols, typename F>
inline auto TryEachProtocol(F&& f)
#ifdef BOND_NO_CXX14_RETURN_TYPE_DEDUCTION
-> decltype(mpl::try_apply<typename Protocols::type>(std::forward<F>(f)))
#endif
{
UnknownProtocolException();
return std::make_pair(MARSHALED_PROTOCOL, false);
return mpl::try_apply<typename Protocols::type>(std::forward<F>(f));
}
template <typename T, typename Buffer, typename Transform, typename Iter, typename EndIter>
inline std::pair<ProtocolType, bool> NextProtocol(
const Iter&,
const EndIter& end,
Buffer& input,
const Transform& transform)
template <typename T, typename Protocols>
struct NextProtocolFunctor
{
typedef typename boost::mpl::deref<Iter>::type Reader;
Reader reader(input);
if (reader.ReadVersion())
template <typename Buffer, typename Transform, typename Reader>
boost::optional<std::pair<ProtocolType, bool> >
operator()(Buffer& input, const Transform& transform, const mpl::identity<Reader>&) const
{
return std::make_pair(
static_cast<ProtocolType>(Reader::magic),
Apply(transform, bonded<T, ProtocolReader>(reader)));
Reader reader(input);
if (reader.ReadVersion())
{
return std::make_pair(
static_cast<ProtocolType>(Reader::magic),
Apply<Protocols>(transform, bonded<T, ProtocolReader>(reader)));
}
return {};
}
else
template <typename Buffer, typename Transform, typename Reader>
boost::optional<bool>
operator()(Buffer& input, const Transform& transform, uint16_t protocol, const mpl::identity<Reader>&) const
{
return NextProtocol<T>(typename boost::mpl::next<Iter>::type(), end, input, transform);
if (Reader::magic == protocol)
{
Reader reader(input);
return Apply<Protocols>(transform, bonded<T, Reader&>(reader));
}
return {};
}
template <template <typename Writer, typename ProtocolsT> class Transform>
struct TransformFunctor
{
template <typename Buffer, typename Reader>
boost::optional<bool>
operator()(const T& value, Buffer& output, uint16_t protocol, const mpl::identity<Reader>&) const
{
if (Reader::magic == protocol)
{
using Writer = typename get_protocol_writer<Reader, Buffer>::type;
Writer writer(output);
return Apply<Protocols>(Transform<Writer, Protocols>(writer), value);
}
return {};
}
};
};
template <typename Protocols>
struct NextProtocolFunctor<void, Protocols>
{
template <typename Buffer, typename Transform, typename Reader>
boost::optional<std::pair<ProtocolType, bool> >
operator()(const RuntimeSchema& schema, Buffer& input, const Transform& transform, const mpl::identity<Reader>&) const
{
Reader reader(input);
if (reader.ReadVersion())
{
return std::make_pair(
static_cast<ProtocolType>(Reader::magic),
Apply<Protocols>(transform, bonded<void, ProtocolReader>(reader, schema)));
}
return {};
}
template <typename Buffer, typename Transform, typename Reader>
boost::optional<bool>
operator()(const RuntimeSchema& schema, Buffer& input, const Transform& transform, uint16_t protocol, const mpl::identity<Reader>&) const
{
if (Reader::magic == protocol)
{
Reader reader(input);
return Apply<Protocols>(transform, bonded<void, Reader&>(reader, schema));
}
return {};
}
};
// Select protocol and apply transform using compile-time schema
template <typename T, typename Protocols, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> NextProtocol(Buffer& input, const Transform& transform)
{
auto&& visitor =
#ifndef BOND_NO_CXX14_GENERIC_LAMBDAS
[&](const auto& identity) { return NextProtocolFunctor<T, Protocols>{}(input, transform, identity); };
#else
std::bind(NextProtocolFunctor<T, Protocols>{}, std::ref(input), std::cref(transform), std::placeholders::_1);
#endif
if (auto&& result = TryEachProtocol<typename Protocols::template FilterBuffer<Buffer> >(std::move(visitor)))
{
return result.get();
}
UnknownProtocolException();
}
// Select protocol and apply transform using runtime schema
template <typename Buffer, typename Transform, typename EndIter>
inline std::pair<ProtocolType, bool> NextProtocol(
const EndIter&,
const EndIter&,
const RuntimeSchema&,
Buffer&,
const Transform&)
template <typename Protocols, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> NextProtocol(const RuntimeSchema& schema, Buffer& input, const Transform& transform)
{
UnknownProtocolException();
return std::make_pair(MARSHALED_PROTOCOL, false);
}
auto&& visitor =
#ifndef BOND_NO_CXX14_GENERIC_LAMBDAS
[&](const auto& identity) { return NextProtocolFunctor<void, Protocols>{}(schema, input, transform, identity); };
#else
std::bind(NextProtocolFunctor<void, Protocols>{}, std::cref(schema), std::ref(input), std::cref(transform), std::placeholders::_1);
#endif
template <typename Buffer, typename Transform, typename Iter, typename EndIter>
inline std::pair<ProtocolType, bool> NextProtocol(
const Iter&,
const EndIter& end,
const RuntimeSchema& schema,
Buffer& input,
const Transform& transform)
{
typedef typename boost::mpl::deref<Iter>::type Reader;
Reader reader(input);
if (reader.ReadVersion())
if (auto&& result = TryEachProtocol<typename Protocols::template FilterBuffer<Buffer> >(std::move(visitor)))
{
return std::make_pair(
static_cast<ProtocolType>(Reader::magic),
Apply(transform, bonded<void, ProtocolReader>(reader, schema)));
}
else
{
return NextProtocol(typename boost::mpl::next<Iter>::type(), end, schema, input, transform);
return result.get();
}
UnknownProtocolException();
}
// Select protocol based on magic number and apply transform using compile-time schema
template <typename T, typename Buffer, typename Transform, typename EndIter>
inline bool NextProtocol(
const EndIter&,
const EndIter&,
Buffer&,
const Transform&, uint16_t protocol)
template <typename T, typename Protocols, typename Buffer, typename Transform>
inline bool NextProtocol(Buffer& input, const Transform& transform, uint16_t protocol)
{
auto&& visitor =
#ifndef BOND_NO_CXX14_GENERIC_LAMBDAS
[&](const auto& identity) { return NextProtocolFunctor<T, Protocols>{}(input, transform, protocol, identity); };
#else
std::bind(NextProtocolFunctor<T, Protocols>{}, std::ref(input), std::cref(transform), protocol, std::placeholders::_1);
#endif
if (auto&& result = TryEachProtocol<typename Protocols::template FilterBuffer<Buffer> >(std::move(visitor)))
{
return result.get();
}
UnknownProtocolException(protocol);
return false;
}
template <typename T, typename Buffer, typename Transform, typename Iter, typename EndIter>
inline bool NextProtocol(
const Iter&,
const EndIter& end,
Buffer& input,
const Transform& transform,
uint16_t protocol)
{
typedef typename boost::mpl::deref<Iter>::type Reader;
if (Reader::magic == protocol)
{
Reader reader(input);
return Apply(transform, bonded<T, Reader&>(reader));
}
else
{
return NextProtocol<T>(typename boost::mpl::next<Iter>::type(), end, input, transform, protocol);
}
}
// Select protocol based on magic number and apply transform using runtime schema
template <typename Buffer, typename Transform, typename EndIter>
inline bool NextProtocol(
const EndIter&,
const EndIter&,
const RuntimeSchema&, Buffer&, const Transform&, uint16_t protocol)
template <typename Protocols, typename Buffer, typename Transform>
inline bool NextProtocol(const RuntimeSchema& schema, Buffer& input, const Transform& transform, uint16_t protocol)
{
UnknownProtocolException(protocol);
return false;
}
auto&& visitor =
#ifndef BOND_NO_CXX14_GENERIC_LAMBDAS
[&](const auto& identity) { return NextProtocolFunctor<void, Protocols>{}(schema, input, transform, protocol, identity); };
#else
std::bind(NextProtocolFunctor<void, Protocols>{}, std::cref(schema), std::ref(input), std::cref(transform), protocol, std::placeholders::_1);
#endif
template <typename Buffer, typename Transform, typename Iter, typename EndIter>
inline bool NextProtocol(
const Iter&,
const EndIter& end,
const RuntimeSchema& schema,
Buffer& input,
const Transform& transform,
uint16_t protocol)
{
typedef typename boost::mpl::deref<Iter>::type Reader;
if (Reader::magic == protocol)
if (auto&& result = TryEachProtocol<typename Protocols::template FilterBuffer<Buffer> >(std::move(visitor)))
{
Reader reader(input);
return Apply(transform, bonded<void, Reader&>(reader, schema));
}
else
{
return NextProtocol(typename boost::mpl::next<Iter>::type(), end, schema, input, transform, protocol);
return result.get();
}
UnknownProtocolException(protocol);
}
// Select protocol based on magic number and apply instance of serializing transform
template <template <typename Writer> class Transform, typename Buffer, typename T, typename EndIter>
inline bool NextProtocol(
const EndIter&,
const EndIter&,
const T&,
Buffer&,
uint16_t protocol)
template <template <typename Writer, typename ProtocolsT> class Transform, typename Protocols, typename T, typename Buffer>
inline bool NextProtocol(const T& value, Buffer& output, uint16_t protocol)
{
using TransformFunctor = typename NextProtocolFunctor<T, Protocols>::template TransformFunctor<Transform>;
auto&& visitor =
#ifndef BOND_NO_CXX14_GENERIC_LAMBDAS
[&](const auto& identity) { return TransformFunctor{}(value, output, protocol, identity); };
#else
std::bind(TransformFunctor{}, std::cref(value), std::ref(output), protocol, std::placeholders::_1);
#endif
if (auto&& result = TryEachProtocol<typename Protocols::FilterEnabled>(std::move(visitor)))
{
return result.get();
}
UnknownProtocolException(protocol);
return false;
}
template <template <typename Writer> class Transform, typename Buffer, typename T, typename Iter, typename EndIter>
inline bool NextProtocol(
const Iter&,
const EndIter& end,
const T& value,
Buffer& output,
uint16_t protocol)
{
typedef typename boost::mpl::deref<Iter>::type Reader;
if (Reader::magic == protocol)
{
typedef typename get_protocol_writer<Reader, Buffer>::type Writer;
Writer writer(output);
return Apply(Transform<Writer>(writer), value);
}
else
{
return NextProtocol<Transform>(typename boost::mpl::next<Iter>::type(), end, value, output, protocol);
}
}
@ -217,74 +238,48 @@ inline bool NextProtocol(
// Use compile-time schema
template <typename T, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> SelectProtocolAndApply(
Buffer& input,
const Transform& transform)
template <typename T, typename Protocols = BuiltInProtocols, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> SelectProtocolAndApply(Buffer& input, const Transform& transform)
{
return detail::NextProtocol<T>(typename FilteredProtocols<Buffer>::begin(), typename FilteredProtocols<Buffer>::end(), input, transform);
return detail::NextProtocol<T, Protocols>(input, transform);
}
// Use runtime schema
template <typename Buffer, typename Transform>
template <typename Protocols = BuiltInProtocols, typename Buffer, typename Transform>
inline std::pair<ProtocolType, bool> SelectProtocolAndApply(
const RuntimeSchema& schema,
Buffer& input,
const Transform& transform)
{
return detail::NextProtocol(typename FilteredProtocols<Buffer>::begin(), typename FilteredProtocols<Buffer>::end(), schema, input, transform);
return detail::NextProtocol<Protocols>(schema, input, transform);
}
// Apply deserializing transform with a protocol specified by magic number
// Use compile-time schema
template <typename T, typename Buffer, typename Transform>
inline bool Apply(
const Transform& transform,
Buffer& input,
uint16_t protocol)
template <typename T, typename Protocols = BuiltInProtocols, typename Transform, typename Buffer>
inline bool Apply(const Transform& transform, Buffer& input, uint16_t protocol)
{
return detail::NextProtocol<T>(
typename FilteredProtocols<Buffer>::begin(),
typename FilteredProtocols<Buffer>::end(),
input,
transform,
protocol
);
return detail::NextProtocol<T, Protocols>(input, transform, protocol);
}
// Use runtime schema
template <typename Buffer, typename Transform>
inline bool Apply(
const Transform& transform,
const RuntimeSchema& schema,
Buffer& input,
uint16_t protocol)
template <typename Protocols = BuiltInProtocols, typename Transform, typename Buffer>
inline bool Apply(const Transform& transform, const RuntimeSchema& schema, Buffer& input, uint16_t protocol)
{
return detail::NextProtocol(
typename FilteredProtocols<Buffer>::begin(),
typename FilteredProtocols<Buffer>::end(),
schema,
input,
transform,
protocol
);
return detail::NextProtocol<Protocols>(schema, input, transform, protocol);
}
// Apply an instance of serializing transform with a protocol specified by magic number
template <template <typename Writer> class Transform, typename Buffer, typename T>
template <template <typename Writer, typename ProtocolsT> class Transform, typename Protocols = BuiltInProtocols, typename T, typename Buffer>
inline bool Apply(const T& value, Buffer& output, uint16_t protocol)
{
return detail::NextProtocol<Transform>(
Protocols::begin(),
Protocols::end(),
value,
output,
protocol);
return detail::NextProtocol<Transform, Protocols>(value, output, protocol);
}
} // namespace bond

Просмотреть файл

@ -8,6 +8,7 @@
#include "bond_fwd.h"
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/static_assert.hpp>
#ifndef BOND_NO_CXX11_HDR_TYPE_TRAITS
# include <type_traits>
@ -99,9 +100,15 @@ is_protocol_same
: false_type {};
template <template <typename T> class Reader, typename I, template <typename T> class Writer, typename O> struct
is_protocol_same<Reader<I>, Writer<O> >
: is_same<typename Reader<O>::Writer, Writer<O> > {};
template <template <typename T> class Reader, typename Input, template <typename T> class Writer, typename Output> struct
is_protocol_same<Reader<Input>, Writer<Output> >
: is_same<typename Reader<Output>::Writer, Writer<Output> > {};
template <template <typename T, typename U> class Reader, typename Input, typename MarshaledBondedProtocols, template <typename T> class Writer, typename Output> struct
is_protocol_same<Reader<Input, MarshaledBondedProtocols>, Writer<Output> >
: is_same<typename Reader<Output, MarshaledBondedProtocols>::Writer, Writer<Output> > {};
// For protocols that have multiple versions, specialize this template...
template <typename Reader> struct
@ -168,6 +175,40 @@ template <typename T> struct
is_type_alias
: is_object<typename aliased_type<T>::type> {};
// is_reader
template <typename Input, typename T = void, typename Enable = void> struct
is_reader
: false_type {};
template <typename Input, typename T> struct
is_reader<Input&, T>
: is_reader<Input, T> {};
template <typename Input, typename T> struct
is_reader<Input, T, typename boost::enable_if<is_class<typename Input::Parser> >::type>
: true_type {};
template <typename T> struct
buffer_magic
{
BOOST_STATIC_ASSERT_MSG(!is_same<T, T>::value, "Undefined buffer.");
};
template <typename T> struct
buffer_magic<T&>
: buffer_magic<T> {};
template <uint16_t Id> struct
unique_buffer_magic_check;
#define BOND_DEFINE_BUFFER_MAGIC(Buffer, Id) \
template <> struct unique_buffer_magic_check<Id> {}; \
template <> struct buffer_magic<Buffer> : std::integral_constant<uint16_t, Id> {}
namespace detail
{

Просмотреть файл

@ -3,6 +3,7 @@
#pragma once
#include "bond_fwd.h"
#include "reflection.h"
#include "exception.h"
#include "null.h"
@ -39,7 +40,7 @@ namespace detail
// Applying this transform to input from parsing serialized data is equivalent
// to transcoding from one protocol to another.
//
template <typename Writer>
template <typename Writer, typename Protocols>
class Serializer
: public SerializingTransform
{
@ -60,9 +61,9 @@ public:
}
template <typename Pass0>
Serializer<Pass0> Rebind(Pass0& pass0) const
Serializer<Pass0, Protocols> Rebind(Pass0& pass0) const
{
return Serializer<Pass0>(pass0);
return Serializer<Pass0, Protocols>(pass0);
}
void Begin(const Metadata& metadata) const
@ -84,7 +85,7 @@ public:
bool Base(const T& value) const
{
// 'true' means that we are writing a base struct
Apply(Serializer<Writer>(_output, true), value);
Apply<Protocols>(Serializer(_output, true), value);
return false;
}
@ -199,7 +200,7 @@ private:
typename boost::enable_if<is_bond_type<T> >::type
Write(const T& value) const
{
Apply(Serializer<Writer>(_output), value);
Apply<Protocols>(Serializer(_output), value);
}
// bonded<T> and untagged writer
@ -207,7 +208,7 @@ private:
typename boost::enable_if<uses_marshaled_bonded<typename Writer::Reader, T> >::type
Write(const bonded<T>& value) const
{
detail::MarshalToBlob(value, _output);
detail::MarshalToBlob<Protocols>(value, _output);
}
// bonded<void> and untagged writer
@ -215,7 +216,7 @@ private:
typename boost::enable_if<uses_marshaled_bonded<typename Writer::Reader, Reader> >::type
Write(const bonded<void, Reader>& value) const
{
value.Serialize(_output);
value.template Serialize<Protocols>(_output);
}
// 2-tuple
@ -258,7 +259,7 @@ private:
{
T data = T();
value.Deserialize(data);
value.template Deserialize<Protocols>(data);
Write(data);
}
@ -266,11 +267,11 @@ private:
typename boost::disable_if<is_basic_type<T> >::type
Write(const value<T, Reader>& value) const
{
Apply(Serializer<Writer>(_output), value);
Apply<Protocols>(Serializer(_output), value);
}
template <typename T, typename WriterT>
template <typename T, typename WriterT, typename ProtocolsT>
friend class Merger;
template <typename T, typename Reader, typename Enable>
@ -279,7 +280,7 @@ private:
template <typename T, typename Schema, typename Transform>
friend class detail::_Parser;
template <typename Transform, typename T>
template <typename ProtocolsT, typename Transform, typename T>
friend bool detail::DoublePassApply(const Transform&, const T&);
protected:
@ -289,29 +290,29 @@ protected:
// SerializeTo
template <typename Writer>
Serializer<Writer> SerializeTo(Writer& output)
template <typename Protocols, typename Writer>
Serializer<Writer, Protocols> SerializeTo(Writer& output)
{
return Serializer<Writer>(output);
return Serializer<Writer, Protocols>(output);
}
template <typename Writer>
template <typename Writer, typename Protocols>
class Marshaler
: protected Serializer<Writer>
: protected Serializer<Writer, Protocols>
{
public:
typedef Writer writer_type;
Marshaler(Writer& output)
: Serializer<Writer>(output)
: Serializer<Writer, Protocols>(output)
{}
template <typename T>
bool Marshal(const T& value) const
{
this->_output.WriteVersion();
return Apply(static_cast<const Serializer<Writer>&>(*this), value);
return Apply<Protocols>(static_cast<const Serializer<Writer, Protocols>&>(*this), value);
}
};
@ -319,17 +320,17 @@ public:
namespace detail
{
template <typename Writer, typename T, typename Reader>
template <typename Protocols, typename Writer, typename T, typename Reader>
bool inline
ApplyTransform(const Marshaler<Writer>& marshaler, const bonded<T, Reader>& bonded)
ApplyTransform(const Marshaler<Writer, Protocols>& marshaler, const bonded<T, Reader>& bonded)
{
return marshaler.Marshal(bonded);
}
template <typename Writer, typename T>
template <typename Protocols, typename Writer, typename T>
bool inline
ApplyTransform(const Marshaler<Writer>& marshaler, const T& value)
ApplyTransform(const Marshaler<Writer, Protocols>& marshaler, const T& value)
{
return marshaler.Marshal(value);
}
@ -338,10 +339,10 @@ ApplyTransform(const Marshaler<Writer>& marshaler, const T& value)
// MarshalTo
template <typename Writer>
Marshaler<Writer> MarshalTo(Writer& output)
template <typename Protocols, typename Writer>
Marshaler<Writer, Protocols> MarshalTo(Writer& output)
{
return Marshaler<Writer>(output);
return Marshaler<Writer, Protocols>(output);
}
@ -410,6 +411,7 @@ void RequiredFieldValiadator<T>::MissingFieldException() const
namespace detail
{
template <typename Protocols>
class To
: public DeserializingTransform
{
@ -426,20 +428,20 @@ protected:
template <typename V, typename X>
void AssignToVar(V& var, const X& value) const
{
value.Deserialize(var);
value.template Deserialize<Protocols>(var);
}
template <typename V, typename X>
void AssignToVar(maybe<V>& var, const X& value) const
{
value.Deserialize(var.set_value());
value.template Deserialize<Protocols>(var.set_value());
}
template <typename V, typename X>
typename boost::enable_if<has_base<V>, bool>::type
AssignToBase(V& var, const X& value) const
{
return Apply(bond::To<typename schema<V>::type::base>(var), value);
return Apply<Protocols>(bond::To<typename schema<V>::type::base, Protocols>(var), value);
}
template <typename V, typename X>
@ -459,9 +461,9 @@ protected:
} // namespace detail
template <typename T, typename Validator>
template <typename T, typename Protocols, typename Validator>
class To
: public detail::To,
: public detail::To<Protocols>,
protected Validator
{
public:
@ -536,8 +538,9 @@ public:
}
private:
using detail::To::AssignToBase;
using detail::To::AssignToField;
using detail::To<Protocols>::AssignToBase;
using detail::To<Protocols>::AssignToVar;
using detail::To<Protocols>::AssignToField;
template <typename Fields, typename X>
bool AssignToField(const Fields&, uint16_t id, const X& value) const
@ -582,6 +585,7 @@ BOND_STATIC_CONSTEXPR uint16_t mapping_base = invalid_field_id;
namespace detail
{
template <typename Protocols>
class MapTo
: public DeserializingTransform
{
@ -602,7 +606,7 @@ public:
}
protected:
struct PathView
struct PathView
: boost::noncopyable
{
PathView(const Path& path)
@ -730,23 +734,23 @@ protected:
template <typename V, typename X>
void AssignToVar(V& var, const X& value) const
{
value.Deserialize(var);
value.template Deserialize<Protocols>(var);
}
template <typename V, typename X>
void AssignToVar(maybe<V>& var, const X& value) const
{
value.Deserialize(var.set_value());
value.template Deserialize<Protocols>(var.set_value());
}
};
} // namespace detail
template <typename T>
template <typename T, typename Protocols = BuiltInProtocols>
class MapTo
: public detail::MapTo
: public detail::MapTo<Protocols>
{
public:
BOOST_STATIC_ASSERT(has_schema<T>::value);
@ -763,7 +767,7 @@ public:
Mappings::const_iterator it = _mappings.find(mapping_base);
if (it != _mappings.end())
return Apply(MapTo(_var, it->second.fields), value);
return Apply<Protocols>(MapTo(_var, it->second.fields), value);
else
return false;
}
@ -781,7 +785,7 @@ public:
return Apply(MapTo(_var, it->second.fields), value);
if (!it->second.path.empty())
return Assign(_var, it->second.path, value);
return this->Assign(_var, it->second.path, value);
}
return false;
@ -795,7 +799,7 @@ public:
Mappings::const_iterator it = _mappings.find(id);
if (it != _mappings.end() && !it->second.path.empty())
return Assign(_var, it->second.path, value);
return this->Assign(_var, it->second.path, value);
else
return false;
}

Просмотреть файл

@ -18,6 +18,7 @@ namespace bond
/// are different but payload in source schema can be deserialized as destination.
/// @throw SchemaValidateException if payload in source schema is incompatible
/// with destination schema.
template <typename Protocols = BuiltInProtocols>
inline bool Validate(const RuntimeSchema& src,
const RuntimeSchema& dst)
{
@ -38,14 +39,15 @@ inline bool Validate(const RuntimeSchema& src,
/// are different but payload in source schema can be deserialized as destination.
/// @throw SchemaValidateException if payload in source schema is incompatible
/// with destination schema or the schema of source SchemaDef is unknown.
template <typename Protocols = BuiltInProtocols>
inline bool Validate(const bonded<SchemaDef>& src,
const RuntimeSchema& dst)
{
Apply(detail::SchemaValidator(), src);
Apply<Protocols>(detail::SchemaValidator<Protocols>(), src);
SchemaDef schema;
src.Deserialize(schema);
return Validate(RuntimeSchema(schema), dst);
src.template Deserialize<Protocols>(schema);
return Validate<Protocols>(RuntimeSchema(schema), dst);
}
@ -56,14 +58,15 @@ inline bool Validate(const bonded<SchemaDef>& src,
/// are different but payload in source schema can be deserialized as destination.
/// @throw SchemaValidateException if payload in source schema is incompatible
/// with destination schema or the schema of destination SchemaDef is unknown.
template <typename Protocols = BuiltInProtocols>
inline bool Validate(const RuntimeSchema& src,
const bonded<SchemaDef>& dst)
{
Apply(detail::SchemaValidator(), dst);
Apply<Protocols>(detail::SchemaValidator<Protocols>(), dst);
SchemaDef schema;
dst.Deserialize(schema);
return Validate(src, RuntimeSchema(schema));
dst.template Deserialize<Protocols>(schema);
return Validate<Protocols>(src, RuntimeSchema(schema));
}
@ -75,10 +78,10 @@ inline bool Validate(const RuntimeSchema& src,
/// and vice versa.
/// @throw SchemaValidateException if payload in any one schema is incompatible
/// with the other schema.
template <typename T1, typename T2>
template <typename Protocols = BuiltInProtocols, typename T1, typename T2>
inline bool ValidateTwoWay(const T1& s1, const T2& s2)
{
return Validate(s1, s2) & Validate(s2, s1);
return Validate<Protocols>(s1, s2) & Validate<Protocols>(s2, s1);
}
} // namespace bond

Просмотреть файл

@ -32,7 +32,9 @@ inline set(X& var, const T& value)
set_aliased_value(var, value);
}
}
} // namespace detail
template <typename X, typename T>
inline X cast(const T& value)
@ -209,7 +211,7 @@ public:
}
// skip value of non-matching type
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::disable_if_c<is_matching<T, X>::value>::type
Deserialize(X& /*var*/) const
{
@ -247,6 +249,7 @@ public:
#endif
/// @brief Deserialize the value
template <typename Protocols = BuiltInProtocols>
void Deserialize(T& var) const
{
_skip = false;
@ -255,6 +258,7 @@ public:
// deserialize series of matching values to blob
template <typename Protocols = BuiltInProtocols>
void Deserialize(blob& var, uint32_t size) const
{
BOOST_STATIC_ASSERT((is_same<T, blob::value_type>::value));
@ -264,7 +268,7 @@ public:
// deserialize the value and cast it to a variable of a matching non-string type
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if_c<is_matching_basic<T, X>::value && !is_string_type<T>::value>::type
Deserialize(X& var) const
{
@ -277,7 +281,7 @@ public:
// deserialize the value to a variable of a matching string type
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if_c<is_matching_basic<T, X>::value && is_string_type<T>::value>::type
Deserialize(X& var) const
{
@ -316,6 +320,7 @@ public:
value& operator=(const value& that) = default;
#endif
template <typename Protocols = BuiltInProtocols>
void Deserialize(T& var) const
{
typename aliased_type<T>::type value;
@ -353,20 +358,20 @@ public:
#endif
// deserialize Bond struct into matching variable
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if<is_bond_type<X> >::type
Deserialize(X& var) const
{
_skip = false;
bonded<T, Reader>(_input).Deserialize(var);
bonded<T, Reader>(_input).template Deserialize<Protocols>(var);
}
template <typename Transform>
template <typename Protocols = BuiltInProtocols, typename Transform>
void _Apply(const Transform& transform) const
{
_skip = false;
Apply(transform, bonded<T, Reader>(_input));
Apply<Protocols>(transform, bonded<T, Reader>(_input));
}
@ -388,6 +393,23 @@ public:
};
template <typename Protocols, typename X, typename T1, typename T2, typename Reader>
inline void DeserializeContainer(X& var, const value<std::pair<T1, T2>, Reader&>&, Reader& input);
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::disable_if<is_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input);
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_nested_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input);
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_basic_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input);
// Specialization of value for containers with compile-time schema
template <typename T, typename Reader>
class value<T, Reader, typename boost::enable_if<is_container<T> >::type>
@ -411,20 +433,20 @@ public:
#endif
// Deserialize container
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if_c<is_matching_container<T, X>::value>::type
Deserialize(X& var) const
{
_skip = false;
DeserializeContainer(var, value<typename element_type<T>::type, Reader>(_input, false), _input);
DeserializeContainer<Protocols>(var, value<typename element_type<T>::type, Reader>(_input, false), _input);
}
template <typename Transform>
template <typename Protocols = BuiltInProtocols, typename Transform>
void _Apply(const Transform& transform) const
{
_skip = false;
DeserializeContainer(transform, value<typename element_type<T>::type, Reader>(_input, false), _input);
DeserializeContainer<Protocols>(transform, value<typename element_type<T>::type, Reader>(_input, false), _input);
}
using value_common<T, Reader>::Deserialize;
@ -436,6 +458,18 @@ protected:
};
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::disable_if<is_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input);
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_nested_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input);
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_basic_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input);
// Specialization of value for data described by runtime schema
template <typename Reader>
@ -491,14 +525,14 @@ public:
// Deserialize container
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if_c<is_container<X>::value && !is_map_container<X>::value>::type
Deserialize(X& var) const
{
if (_schema.GetTypeId() == get_type_id<X>::value)
{
_skip = false;
DeserializeContainer(var,
DeserializeContainer<Protocols>(var,
value<void, Reader>(_input, element_schema(_schema), false), _input);
}
else
@ -509,14 +543,14 @@ public:
// Deserialize map
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if<is_map_container<X> >::type
Deserialize(X& var) const
{
if (_schema.GetTypeId() == get_type_id<X>::value)
{
_skip = false;
DeserializeMap(var, key_schema(_schema).GetTypeId(),
DeserializeMap<Protocols>(var, key_schema(_schema).GetTypeId(),
value<void, Reader>(_input, element_schema(_schema), false), _input);
}
else
@ -527,14 +561,14 @@ public:
// Deserialize Bond struct
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::enable_if<is_bond_type<X> >::type
Deserialize(X& var) const
{
if (_schema.GetTypeId() == get_type_id<X>::value)
{
_skip = false;
bonded<void, Reader>(_input, _schema).Deserialize(var);
bonded<void, Reader>(_input, _schema).template Deserialize<Protocols>(var);
}
else
{
@ -543,32 +577,32 @@ public:
}
template <typename Transform>
template <typename Protocols = BuiltInProtocols, typename Transform>
void _Apply(const Transform& transform) const
{
_skip = false;
if (_schema.GetTypeId() == bond::BT_STRUCT)
{
Apply(transform, bonded<void, Reader>(_input, _schema));
Apply<Protocols>(transform, bonded<void, Reader>(_input, _schema));
}
else if(_schema.GetTypeId() == bond::BT_MAP)
{
DeserializeMap(transform, key_schema(_schema).GetTypeId(),
DeserializeMap<Protocols>(transform, key_schema(_schema).GetTypeId(),
value<void, Reader>(_input, element_schema(_schema), false), _input);
}
else
{
BOOST_ASSERT(_schema.GetTypeId() == bond::BT_LIST || _schema.GetTypeId() == bond::BT_SET);
DeserializeContainer(transform,
DeserializeContainer<Protocols>(transform,
value<void, Reader>(_input, element_schema(_schema), false), _input);
}
}
// skip value of non-matching type
template <typename X>
template <typename Protocols = BuiltInProtocols, typename X>
typename boost::disable_if_c<is_container<X>::value || is_bond_type<X>::value>::type
Deserialize(X& /*var*/) const
{
@ -595,7 +629,7 @@ private:
};
template <typename X, typename I, typename T>
template <typename Protocols, typename X, typename I, typename T>
typename boost::enable_if<require_modify_element<X> >::type
inline DeserializeElement(X& var, const I& item, const T& element)
{
@ -607,7 +641,7 @@ inline DeserializeElement(X& var, const I& item, const T& element)
void operator()(typename element_type<X>::type& e)
{
this->element.Deserialize(e);
this->element.template Deserialize<Protocols>(e);
}
const T& element;
@ -617,16 +651,16 @@ inline DeserializeElement(X& var, const I& item, const T& element)
}
template <typename X, typename I, typename T>
template <typename Protocols, typename X, typename I, typename T>
typename boost::disable_if<require_modify_element<X> >::type
inline DeserializeElement(X&, I& item, const T& element)
{
element.Deserialize(item);
element.template Deserialize<Protocols>(item);
}
// Read elements of a list
template <typename X, typename T>
template <typename Protocols, typename X, typename T>
typename boost::enable_if_c<is_list_container<X>::value
&& is_element_matching<T, X>::value>::type
inline DeserializeElements(X& var, const T& element, uint32_t size)
@ -634,18 +668,18 @@ inline DeserializeElements(X& var, const T& element, uint32_t size)
resize_list(var, size);
for (enumerator<X> items(var); items.more();)
DeserializeElement(var, items.next(), element);
DeserializeElement<Protocols>(var, items.next(), element);
}
template <typename X, typename Allocator, bool useValue, typename T>
template <typename Protocols, typename X, typename Allocator, bool useValue, typename T>
typename boost::enable_if<is_matching<T, X> >::type
inline DeserializeElements(nullable<X, Allocator, useValue>& var, const T& element, uint32_t size)
{
resize_list(var, size);
for (enumerator<nullable<X, Allocator, useValue> > items(var); items.more(); --size)
element.Deserialize(items.next());
element.template Deserialize<Protocols>(items.next());
// Wire representation and interface for nullable is the same as for list.
// However nullable can "contain" at most one element. If there are more
@ -655,14 +689,14 @@ inline DeserializeElements(nullable<X, Allocator, useValue>& var, const T& eleme
}
template <typename Reader>
template <typename Protocols, typename Reader>
inline void DeserializeElements(blob& var, const value<blob::value_type, Reader&>& element, uint32_t size)
{
element.Deserialize(var, size);
element.template Deserialize<Protocols>(var, size);
}
template <typename X, typename T>
template <typename Protocols, typename X, typename T>
typename boost::enable_if_c<is_set_container<X>::value
&& is_element_matching<T, X>::value>::type
inline DeserializeElements(X& var, const T& element, uint32_t size)
@ -673,13 +707,13 @@ inline DeserializeElements(X& var, const T& element, uint32_t size)
while (size--)
{
element.Deserialize(e);
element.template Deserialize<Protocols>(e);
set_insert(var, e);
}
}
template <typename X, typename T>
template <typename Protocols, typename X, typename T>
typename boost::disable_if<is_element_matching<T, X> >::type
inline DeserializeElements(X&, const T& element, uint32_t size)
{
@ -688,7 +722,7 @@ inline DeserializeElements(X&, const T& element, uint32_t size)
}
template <typename Transform, typename T>
template <typename Protocols, typename Transform, typename T>
inline void DeserializeElements(const Transform& transform, const T& element, uint32_t size)
{
transform.Container(element, size);
@ -723,14 +757,14 @@ inline void SkipContainer(const T& element, Reader& input)
}
template <typename X, typename T1, typename T2, typename Reader>
template <typename Protocols, typename X, typename T1, typename T2, typename Reader>
inline void DeserializeContainer(X& var, const value<std::pair<T1, T2>, Reader&>&, Reader& input)
{
return DeserializeMap(var, get_type_id<T1>::value, value<T2, Reader&>(input, false), input);
return DeserializeMap<Protocols>(var, get_type_id<T1>::value, value<T2, Reader&>(input, false), input);
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::disable_if<is_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input)
{
@ -748,17 +782,17 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
{
if (type == GetTypeId(element))
{
DeserializeElements(var, element, size);
DeserializeElements<Protocols>(var, element, size);
}
else
{
DeserializeElements(var, value<void, Reader&>(input, type, false), size);
DeserializeElements<Protocols>(var, value<void, Reader&>(input, type, false), size);
}
break;
}
default:
{
detail::BasicTypeContainer(var, type, input, size);
detail::BasicTypeContainer<Protocols>(var, type, input, size);
break;
}
}
@ -767,7 +801,7 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_nested_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input)
{
@ -778,7 +812,7 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
if (type == GetTypeId(element))
{
DeserializeElements(var, element, size);
DeserializeElements<Protocols>(var, element, size);
}
else
{
@ -790,7 +824,7 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_basic_container<X> >::type
inline DeserializeContainer(X& var, const T& element, Reader& input)
{
@ -820,7 +854,7 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
}
default:
{
detail::MatchingTypeContainer(var, type, input, size);
detail::MatchingTypeContainer<Protocols>(var, type, input, size);
break;
}
}
@ -829,7 +863,7 @@ inline DeserializeContainer(X& var, const T& element, Reader& input)
}
template <typename X, typename Key, typename T>
template <typename Protocols, typename X, typename Key, typename T>
typename boost::enable_if<is_map_key_matching<Key, X> >::type
inline DeserializeMapElements(X& var, const Key& key, const T& element, uint32_t size)
{
@ -841,21 +875,21 @@ inline DeserializeMapElements(X& var, const Key& key, const T& element, uint32_t
while (size--)
{
key.Deserialize(k);
key.template Deserialize<Protocols>(k);
#ifndef NDEBUG
// In debug build To<T> asserts that optional fields are set to default
// values before deserialization; if invalid map payload contains duplicate
// keys the second time we deserialize a value it will trigger the assert.
element.Deserialize(mapped_at(var, k) = make_value(var));
element.template Deserialize<Protocols>(mapped_at(var, k) = make_value(var));
#else
element.Deserialize(mapped_at(var, k));
element.template Deserialize<Protocols>(mapped_at(var, k));
#endif
}
}
template <typename X, typename Key, typename T>
template <typename Protocols, typename X, typename Key, typename T>
typename boost::disable_if<is_map_key_matching<Key, X> >::type
inline DeserializeMapElements(X&, const Key& key, const T& element, uint32_t size)
{
@ -867,7 +901,7 @@ inline DeserializeMapElements(X&, const Key& key, const T& element, uint32_t siz
}
template <typename Transform, typename Key, typename T>
template <typename Protocols, typename Transform, typename Key, typename T>
inline void DeserializeMapElements(const Transform& transform, const Key& key, const T& element, uint32_t size)
{
transform.Container(key, element, size);
@ -897,7 +931,7 @@ inline void SkipMap(BondDataType keyType, const T& element, Reader& input)
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::disable_if<is_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input)
{
@ -915,17 +949,17 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
{
if (type.second == GetTypeId(element))
{
detail::MapByKey(var, type.first, element, input, size);
detail::MapByKey<Protocols>(var, type.first, element, input, size);
}
else
{
detail::MapByKey(var, type.first, value<void, Reader&>(input, type.second, false), input, size);
detail::MapByKey<Protocols>(var, type.first, value<void, Reader&>(input, type.second, false), input, size);
}
break;
}
default:
{
detail::MapByElement(var, type.first, type.second, input, size);
detail::MapByElement<Protocols>(var, type.first, type.second, input, size);
break;
}
}
@ -934,7 +968,7 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_nested_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input)
{
@ -945,7 +979,7 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
if (type.second == GetTypeId(element))
{
detail::MapByKey(var, type.first, element, input, size);
detail::MapByKey<Protocols>(var, type.first, element, input, size);
}
else
{
@ -960,7 +994,7 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
}
template <typename X, typename T, typename Reader>
template <typename Protocols, typename X, typename T, typename Reader>
typename boost::enable_if<is_basic_container<X> >::type
inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& input)
{
@ -996,7 +1030,7 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
}
default:
{
detail::MatchingMapByElement(var, type.first, type.second, input, size);
detail::MatchingMapByElement<Protocols>(var, type.first, type.second, input, size);
break;
}
}
@ -1004,4 +1038,5 @@ inline DeserializeMap(X& var, BondDataType keyType, const T& element, Reader& in
input.ReadContainerEnd();
}
} // namespace bond

Просмотреть файл

@ -71,7 +71,7 @@ class SimpleBinaryWriter;
/// @brief Reader for Simple Binary protocol
template <typename BufferT>
template <typename BufferT, typename MarshaledBondedProtocolsT>
class SimpleBinaryReader
{
public:
@ -257,9 +257,9 @@ protected:
}
template <typename Input, typename Output>
template <typename Input, typename MarshaledBondedProtocols, typename Output>
friend
bool is_protocol_version_same(const SimpleBinaryReader<Input>&,
bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>&,
const SimpleBinaryWriter<Output>&);
Buffer _input;
@ -267,8 +267,8 @@ protected:
};
template <typename Buffer>
BOND_CONSTEXPR_OR_CONST uint16_t SimpleBinaryReader<Buffer>::magic;
template <typename BufferT, typename MarshaledBondedProtocolsT>
BOND_CONSTEXPR_OR_CONST uint16_t SimpleBinaryReader<BufferT, MarshaledBondedProtocolsT>::magic;
/// @brief Writer for Simple Binary protocol
@ -372,9 +372,9 @@ protected:
WriteVariableUnsigned(_output, size);
}
template <typename Input, typename Output>
template <typename Input, typename MarshaledBondedProtocols, typename Output>
friend
bool is_protocol_version_same(const SimpleBinaryReader<Input>&,
bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>&,
const SimpleBinaryWriter<Output>&);
Buffer& _output;
@ -382,13 +382,13 @@ protected:
};
template <typename Input> struct
protocol_has_multiple_versions<SimpleBinaryReader<Input> >
template <typename Input, typename MarshaledBondedProtocols> struct
protocol_has_multiple_versions<SimpleBinaryReader<Input, MarshaledBondedProtocols> >
: true_type {};
template <typename Input, typename Output>
bool is_protocol_version_same(const SimpleBinaryReader<Input>& reader,
template <typename Input, typename MarshaledBondedProtocols, typename Output>
bool is_protocol_version_same(const SimpleBinaryReader<Input, MarshaledBondedProtocols>& reader,
const SimpleBinaryWriter<Output>& writer)
{
return reader._version == writer._version;

Просмотреть файл

@ -6,12 +6,11 @@
namespace bond
{
template <typename BufferT>
template <typename BufferT, typename MarshaledBondedProtocolsT>
template <typename T>
inline void SimpleBinaryReader<BufferT>::Skip(const bonded<T, SimpleBinaryReader&>& bonded)
inline void SimpleBinaryReader<BufferT, MarshaledBondedProtocolsT>::Skip(const bonded<T, SimpleBinaryReader&>& bonded)
{
// Skip the structure field-by-field by applying Null transform
Apply(Null(), bonded);
detail::Skip(bonded);
}

Просмотреть файл

@ -152,21 +152,21 @@ private:
template <typename Input>
friend struct base_input;
template <typename A, typename T, typename Buffer>
template <typename Protocols, typename A, typename T, typename Buffer>
friend void DeserializeContainer(std::vector<bool, A>&, const T&, SimpleJsonReader<Buffer>&);
template <typename T, typename Buffer>
template <typename Protocols, typename T, typename Buffer>
friend void DeserializeContainer(blob&, const T&, SimpleJsonReader<Buffer>&);
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
friend typename boost::enable_if<is_list_container<X> >::type
DeserializeContainer(X&, const T&, SimpleJsonReader<Buffer>&);
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
friend typename boost::enable_if<is_set_container<X> >::type
DeserializeContainer(X&, const T&, SimpleJsonReader<Buffer>&);
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
friend typename boost::enable_if<is_map_container<X> >::type
DeserializeMap(X&, BondDataType, const T&, SimpleJsonReader<Buffer>&);

Просмотреть файл

@ -37,7 +37,7 @@ SimpleJsonReader<BufferT>::FindField(uint16_t id, const Metadata& metadata, Bond
}
// deserialize std::vector<bool>
template <typename A, typename T, typename Buffer>
template <typename Protocols, typename A, typename T, typename Buffer>
inline void DeserializeContainer(std::vector<bool, A>& var, const T& /*element*/, SimpleJsonReader<Buffer>& reader)
{
rapidjson::Value::ConstValueIterator it = reader.ArrayBegin();
@ -51,7 +51,7 @@ inline void DeserializeContainer(std::vector<bool, A>& var, const T& /*element*/
// deserialize blob
template <typename T, typename Buffer>
template <typename Protocols, typename T, typename Buffer>
inline void DeserializeContainer(blob& var, const T& /*element*/, SimpleJsonReader<Buffer>& reader)
{
if (uint32_t size = reader.ArraySize())
@ -71,7 +71,7 @@ inline void DeserializeContainer(blob& var, const T& /*element*/, SimpleJsonRead
// deserialize list
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
inline typename boost::enable_if<is_list_container<X> >::type
DeserializeContainer(X& var, const T& element, SimpleJsonReader<Buffer>& reader)
{
@ -87,12 +87,12 @@ DeserializeContainer(X& var, const T& element, SimpleJsonReader<Buffer>& reader)
if (type.ComplexTypeMatch(*it))
{
SimpleJsonReader<Buffer> input(reader, *it);
DeserializeElement(var, items.next(), detail::MakeValue(input, element));
DeserializeElement<Protocols>(var, items.next(), detail::MakeValue(input, element));
}
else if (type.BasicTypeMatch(*it))
{
SimpleJsonReader<Buffer> input(reader, *it);
DeserializeElement(var, items.next(), value<typename element_type<X>::type, SimpleJsonReader<Buffer>&>(input));
DeserializeElement<Protocols>(var, items.next(), value<typename element_type<X>::type, SimpleJsonReader<Buffer>&>(input));
}
else
{
@ -103,7 +103,7 @@ DeserializeContainer(X& var, const T& element, SimpleJsonReader<Buffer>& reader)
// deserialize set
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
inline typename boost::enable_if<is_set_container<X> >::type
DeserializeContainer(X& var, const T& element, SimpleJsonReader<Buffer>& reader)
{
@ -126,7 +126,7 @@ DeserializeContainer(X& var, const T& element, SimpleJsonReader<Buffer>& reader)
// deserialize map
template <typename X, typename T, typename Buffer>
template <typename Protocols, typename X, typename T, typename Buffer>
inline typename boost::enable_if<is_map_container<X> >::type
DeserializeMap(X& var, BondDataType keyType, const T& element, SimpleJsonReader<Buffer>& reader)
{
@ -154,7 +154,7 @@ DeserializeMap(X& var, BondDataType keyType, const T& element, SimpleJsonReader<
SimpleJsonReader<Buffer> input(reader, *++it);
if (value_type.ComplexTypeMatch(*it))
detail::MakeValue(input, element).Deserialize(mapped_at(var, key));
detail::MakeValue(input, element).template Deserialize<Protocols>(mapped_at(var, key));
else
value<typename element_type<X>::type::second_type, SimpleJsonReader<Buffer>&>(input).Deserialize(mapped_at(var, key));
}

Просмотреть файл

@ -208,7 +208,7 @@ private:
_output.Write(" ", _indent);
}
template <typename Writer>
template <typename Writer, typename Protocols>
friend class Serializer;
detail::RapidJsonOutputStream<BufferT> _stream;
@ -226,8 +226,8 @@ is_writer<SimpleJsonWriter<Buffer>, void>
: true_type {};
template <typename Buffer>
class Serializer<SimpleJsonWriter<Buffer> >
template <typename Buffer, typename Protocols>
class Serializer<SimpleJsonWriter<Buffer>, Protocols>
: public SerializingTransform
{
public:
@ -257,7 +257,7 @@ public:
template <typename T>
bool Base(const T& value) const
{
Apply(*this, value);
Apply<Protocols>(*this, value);
return false;
}
@ -419,7 +419,7 @@ private:
typename boost::enable_if<is_bond_type<T> >::type
Write(const T& value) const
{
Apply(SerializeTo(_output), value);
Apply<Protocols>(SerializeTo<Protocols>(_output), value);
}
// 2-tuple
@ -468,7 +468,7 @@ private:
{
T data;
value.Deserialize(data);
value.template Deserialize<Protocols>(data);
_output.Write(data);
}
@ -476,7 +476,7 @@ private:
typename boost::disable_if<is_basic_type<T> >::type
Write(const value<T, Reader>& value) const
{
Apply(SerializeTo(_output), value);
Apply<Protocols>(SerializeTo<Protocols>(_output), value);
}
protected:

Просмотреть файл

@ -240,18 +240,19 @@ protected:
{
return input._blob.range(input._pointer);
}
friend InputBuffer CreateInputBuffer(const InputBuffer& /*other*/, const blob& blob)
{
return InputBuffer(blob);
}
};
inline InputBuffer CreateInputBuffer(const InputBuffer& /*other*/, const blob& blob)
{
return InputBuffer(blob);
}
inline blob GetBufferRange(const blob& begin, const blob& end)
{
return begin.range(0, begin.length() - end.length());
}
BOND_DEFINE_BUFFER_MAGIC(InputBuffer, 0x4249 /*IB*/);
} // namespace bond

Просмотреть файл

@ -23,7 +23,7 @@ TEST_CASE_BEGIN(AllocatorTest)
Reader reader(data);
bond::Deserialize(reader, *to);
UT_AssertIsTrue(*from == *to);
UT_Compare(*from, *to);
boost::shared_ptr<T> x = boost::allocate_shared<T>(alloc, alloc);
boost::shared_ptr<T> y = boost::allocate_shared<T>(alloc, alloc);
@ -32,7 +32,7 @@ TEST_CASE_BEGIN(AllocatorTest)
y->swap(*to);
UT_AssertIsTrue(*x == *y);
UT_Compare(*x, *y);
}
// Runtime-time deserialize
@ -43,7 +43,7 @@ TEST_CASE_BEGIN(AllocatorTest)
bond::bonded<void> bonded(reader, bond::GetRuntimeSchema<T>());
bonded.Deserialize(*to);
UT_AssertIsTrue(*from == *to);
UT_Compare(*from, *to);
}
}
TEST_CASE_END

Просмотреть файл

@ -24,13 +24,13 @@ void Marshal(uint16_t version = bond::v1)
bond::OutputBuffer output;
Factory<Writer>::Call(output, version, boost::bind(
bond::Marshal<X, Writer>, obj, _1));
bond::Marshal<bond::BuiltInProtocols, X, Writer>, obj, _1));
bond::InputBuffer input = output.GetBuffer();
Unmarshal(input, obj2);
UT_AssertIsTrue(obj == obj2);
UT_Compare(obj, obj2);
}
@ -43,14 +43,14 @@ void Serialize(uint16_t version = bond::v1)
bond::OutputBuffer output;
Factory<Writer>::Call(output, version, boost::bind(
bond::Serialize<X, Writer>, obj, _1));
bond::Serialize<bond::BuiltInProtocols, X, Writer>, obj, _1));
bond::InputBuffer input = output.GetBuffer();
Reader reader(Factory<Reader>::Create(input, version));
Deserialize(reader, obj2);
UT_AssertIsTrue(obj == obj2);
UT_Compare(obj, obj2);
}
@ -69,7 +69,7 @@ void Apply(uint16_t version = bond::v1)
bond::OutputBuffer output;
Factory<Writer>::Call(output, version, boost::bind(
CallApply<bond::Serializer<Writer>, X>, boost::bind(bond::SerializeTo<Writer>, _1), obj));
CallApply<bond::Serializer<Writer>, X>, boost::bind(bond::SerializeTo<bond::BuiltInProtocols, Writer>, _1), obj));
bond::InputBuffer input = output.GetBuffer();
Reader reader(Factory<Reader>::Create(input, version));
@ -77,7 +77,7 @@ void Apply(uint16_t version = bond::v1)
Apply(bond::To<X>(obj2), bonded);
UT_AssertIsTrue(obj == obj2);
UT_Compare(obj, obj2);
}
@ -91,7 +91,7 @@ void SimpleApply(uint16_t version = bond::v1)
typename Writer::Buffer output;
Factory<Writer>::Call(output, version, boost::bind(
CallApply<bond::Serializer<Writer>, X>, boost::bind(bond::SerializeTo<Writer>, _1), obj));
CallApply<bond::Serializer<Writer>, X>, boost::bind(bond::SerializeTo<bond::BuiltInProtocols, Writer>, _1), obj));
}
@ -114,7 +114,7 @@ Bonded(uint16_t version = bond::v1)
bond::OutputBuffer output;
Factory<Writer>::Call(output, version, boost::bind(
bond::Serialize<X, Writer>, obj, _1));
bond::Serialize<bond::BuiltInProtocols, X, Writer>, obj, _1));
bond::InputBuffer input = output.GetBuffer();
Reader reader(Factory<Reader>::Create(input, version));
@ -122,7 +122,7 @@ Bonded(uint16_t version = bond::v1)
bond::OutputBuffer output2;
Factory<Writer>::Call(output2, version, boost::bind(
&bond::bonded<X>::template Serialize<Writer>, bonded, _1));
&bond::bonded<X>::template Serialize<bond::BuiltInProtocols, Writer>, bonded, _1));
bond::InputBuffer input2 = output2.GetBuffer();
Reader reader2(Factory<Reader>::Create(input2, version));
@ -130,7 +130,7 @@ Bonded(uint16_t version = bond::v1)
bonded2.Deserialize(obj2);
UT_AssertIsTrue(obj == obj2);
UT_Compare(obj, obj2);
}

Просмотреть файл

@ -1,15 +1,6 @@
#include <bond/core/bond_version.h>
#include <bond/stream/output_counter.h>
namespace bond
{
// Use Simple Protocol v2 by default
template <typename Buffer> struct
default_version<SimpleBinaryReader<Buffer> >
: std::integral_constant<uint16_t, 2> {};
};
#include "precompiled.h"
#include "basic_tests.h"
@ -156,46 +147,46 @@ struct SwapTest
{
X x1, x2, y1, y2;
UT_AssertIsTrue(x1 == x2);
UT_AssertIsTrue(y1 == y2);
UT_Compare(x1, x2);
UT_Compare(y1, y2);
x1 = InitRandom<X>();
y1 = InitRandom<X>();
UT_AssertIsTrue(x1 != x2);
UT_AssertIsTrue(y1 != y2);
UT_NegateCompare(x1, x2);
UT_NegateCompare(y1, y2);
x2 = x1;
y2 = y1;
UT_AssertIsTrue(x1 == x2);
UT_AssertIsTrue(y1 == y2);
UT_Compare(x1, x2);
UT_Compare(y1, y2);
x2 = InitRandom<X>();
y2 = InitRandom<X>();
X x3(x1), x4(x2), y3(y1), y4(y2);
UT_AssertIsTrue(x1 == x3);
UT_AssertIsTrue(y1 == y3);
UT_Compare(x1, x3);
UT_Compare(y1, y3);
UT_AssertIsTrue(x2 == x4);
UT_AssertIsTrue(y2 == y4);
UT_Compare(x2, x4);
UT_Compare(y2, y4);
UT_AssertIsTrue(x1 != x4);
UT_AssertIsTrue(y1 != y4);
UT_NegateCompare(x1, x4);
UT_NegateCompare(y1, y4);
UT_AssertIsTrue(x3 != x2);
UT_AssertIsTrue(y3 != y2);
UT_NegateCompare(x3, x2);
UT_NegateCompare(y3, y2);
swap(x1, x2);
y1.swap(y2);
UT_AssertIsTrue(x1 == x4);
UT_AssertIsTrue(y1 == y4);
UT_Compare(x1, x4);
UT_Compare(y1, y4);
UT_AssertIsTrue(x3 == x2);
UT_AssertIsTrue(y3 == y2);
UT_Compare(x3, x2);
UT_Compare(y3, y2);
}
};
@ -226,11 +217,11 @@ struct CopyMoveTest
X src = InitRandom<X>();
X x(src);
UT_AssertIsTrue(x == src);
UT_Compare(x, src);
#ifndef BOND_NO_CXX11_RVALUE_REFERENCES
X y(std::move(x));
UT_AssertIsTrue(y == src);
UT_Compare(y, src);
UT_AssertIsTrue(moved(x));
#endif
}
@ -308,11 +299,13 @@ TEST_CASE_END
TEST_CASE_BEGIN(SimpleBinaryVersion)
{
BOOST_STATIC_ASSERT(bond::default_version<bond::SimpleBinaryReader<bond::InputBuffer>>::value == bond::v1);
SimpleListsStruct from = InitRandom<SimpleListsStruct>();
{
bond::OutputBuffer output_buffer;
// serialize using default version of SimpleBinary reader
bond::SimpleBinaryWriter<bond::OutputBuffer> output(output_buffer);
@ -320,32 +313,32 @@ TEST_CASE_BEGIN(SimpleBinaryVersion)
bond::InputBuffer input_buffer(output_buffer.GetBuffer());
{
// deserialize using version 2 of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer, 2);
// deserialize using version 1 of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer, 1);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
// deserialize using default version of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
{
bond::OutputBuffer output_buffer;
// serialize using version 2 of SimpleBinary writer
bond::SimpleBinaryWriter<bond::OutputBuffer> output(output_buffer, 2);
@ -355,29 +348,18 @@ TEST_CASE_BEGIN(SimpleBinaryVersion)
{
// deserialize using version 2 of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer, 2);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_AssertIsTrue(from == to);
}
{
// deserialize using default version of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
{
bond::OutputBuffer output_buffer;
// serialize using version 1 of SimpleBinary writer
bond::SimpleBinaryWriter<bond::OutputBuffer> output(output_buffer, 1);
@ -387,12 +369,23 @@ TEST_CASE_BEGIN(SimpleBinaryVersion)
{
// deserialize using version 1 of SimpleBinary reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer, 1);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
// deserialize using default version of SimpleProtocol reader
bond::SimpleBinaryReader<bond::InputBuffer> input(input_buffer);
SimpleListsStruct to;
bond::Deserialize(input, to);
UT_Compare(from, to);
}
}
}

Просмотреть файл

@ -9,12 +9,12 @@ void BondedVoid(const bond::bonded<void>& bonded, const T& expected)
bonded.Deserialize(value);
UT_AssertIsTrue(Equal(expected, value));
UT_Equal(expected, value);
CopyAndMove(value);
auto value2 = bonded.Deserialize<T>();
UT_AssertIsTrue(Equal(expected, value2));
UT_Equal(expected, value2);
}
@ -25,12 +25,12 @@ void BondedTyped(const bond::bonded<T>& bonded, const T& expected)
bonded.Deserialize(value);
UT_AssertIsTrue(Equal(expected, value));
UT_Equal(expected, value);
CopyAndMove(value);
auto value2 = bonded.Deserialize();
UT_AssertIsTrue(Equal(expected, value2));
UT_Equal(expected, value2);
}
@ -41,10 +41,10 @@ void BondedCast(const bond::bonded<T1>& bonded, const T2& expected)
bonded.Deserialize(value);
UT_AssertIsTrue(Equal(expected, value));
UT_Equal(expected, value);
auto value2 = bonded.template Deserialize<T2>();
UT_AssertIsTrue(Equal(expected, value2));
UT_Equal(expected, value2);
}
@ -103,14 +103,14 @@ TEST_CASE_BEGIN(BondedConstructors)
simple.m_int8++;
UT_AssertIsTrue(from == from2);
UT_Compare(from, from2);
NestedStruct1 to, to2;
SerializeDeserialize<Reader, Writer>(from, to);
SerializeDeserialize<Reader, Writer>(from2, to2, Reader::version);
UT_AssertIsTrue(simple != original);
UT_NegateCompare(simple, original);
UT_Equal(to.s, original);
UT_Equal(to, to2);
}
@ -124,14 +124,14 @@ TEST_CASE_BEGIN(BondedConstructors)
simple.m_int8++;
UT_AssertIsTrue(from == from2);
UT_Compare(from, from2);
NestedStruct1 to, to2;
SerializeDeserialize<Reader, Writer>(from, to);
SerializeDeserialize<Reader, Writer>(from2, to2, Reader::version);
UT_AssertIsTrue(simple != original);
UT_NegateCompare(simple, original);
UT_Equal(to.s, simple);
UT_Equal(to, to2);
}
@ -147,15 +147,15 @@ TEST_CASE_BEGIN(BondedConstructors)
simple.m_int8++;
simple_ptr->m_int16++;
UT_AssertIsTrue(from == from2);
UT_Compare(from, from2);
NestedStruct1 to, to2;
SerializeDeserialize<Reader, Writer>(from, to);
SerializeDeserialize<Reader, Writer>(from2, to2, Reader::version);
UT_AssertIsTrue(*simple_ptr != original);
UT_AssertIsTrue(*simple_ptr != simple);
UT_NegateCompare(*simple_ptr, original);
UT_NegateCompare(*simple_ptr, simple);
UT_Equal(to.s, *simple_ptr);
UT_Equal(to, to2);
}
@ -199,7 +199,7 @@ TEST_CASE_BEGIN(BondedConstructors)
from2 = from;
UT_AssertIsTrue(from == from2);
UT_Compare(from, from2);
NestedWithBase1BaseView to, to2;
@ -261,13 +261,13 @@ TEST_CASE_BEGIN(MarshaledBonded)
From to;
UT_AssertIsTrue(bond::Validate(bond::GetRuntimeSchema<From>(), bond::GetRuntimeSchema<From>()));
bond::Deserialize(reader, to);
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
From to;
bond::Deserialize(reader, to, bond::GetRuntimeSchema<From>());
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
// 1.b. Deserialize To
@ -275,7 +275,7 @@ TEST_CASE_BEGIN(MarshaledBonded)
To to;
UT_AssertIsFalse(bond::Validate(bond::GetRuntimeSchema<From>(), bond::GetRuntimeSchema<To>()));
bond::Deserialize(reader, to, bond::GetRuntimeSchema<From>());
UT_AssertIsTrue(Equal(from.field, to.field));
UT_Equal(from.field, to.field);
}
}
TEST_CASE_END
@ -299,13 +299,13 @@ TEST_CASE_BEGIN(MarshaledBondedDerived)
To to;
UT_AssertIsTrue(bond::Validate(bond::GetRuntimeSchema<From>(), bond::GetRuntimeSchema<To>()));
bond::Deserialize(reader, to);
UT_AssertIsTrue(Equal(t2, to.field));
UT_Equal(t2, to.field);
}
{
To to;
bond::Deserialize(reader, to, bond::GetRuntimeSchema<From>());
UT_AssertIsTrue(Equal(t2, to.field));
UT_Equal(t2, to.field);
}
// 1.b. Deserialize T2
@ -315,7 +315,7 @@ TEST_CASE_BEGIN(MarshaledBondedDerived)
// to deserialize into instance of T2 directly instead of going via bonded<T2>
UT_AssertIsFalse(bond::Validate(bond::GetRuntimeSchema<To>(), bond::GetRuntimeSchema<To2>()));
bond::Deserialize(reader, to, bond::GetRuntimeSchema<To>());
UT_AssertIsTrue(Equal(t2, to.field));
UT_Equal(t2, to.field);
}
}
TEST_CASE_END

Просмотреть файл

@ -3,52 +3,53 @@
#include "precompiled.h"
#include "container_extensibility.h"
namespace unittest
{
template <typename T, size_t N, typename S>
bool operator==(const std::array<T, N>& left, const S& right)
template <typename Protocols, typename T, size_t N, typename S>
bool Compare(const std::array<T, N>& left, const S& right)
{
for (typename S::size_type i = 0; i < right.length(); ++i)
if (left[i] != static_cast<T>(right[i]))
for (typename S::size_type i = 0; i < right.size(); ++i)
if (!Compare<Protocols>(left[i], static_cast<T>(right[i])))
return false;
return true;
}
inline bool operator==(const WithStaticString& custom, const BondStruct<string>& standard)
template <typename Protocols>
bool Compare(const WithStaticString& custom, const BondStruct<string>& standard)
{
return custom.field == standard.field;
return Compare<Protocols>(custom.field, standard.field);
}
inline bool operator==(const BondStruct<string>& standard, const WithStaticString& custom)
template <typename Protocols>
bool Compare(const BondStruct<string>& standard, const WithStaticString& custom)
{
return custom.field == standard.field;
return Compare<Protocols>(custom.field, standard.field);
}
inline bool operator==(const WithStaticWString& custom, const BondStruct<wstring>& standard)
template <typename Protocols>
bool Compare(const WithStaticWString& custom, const BondStruct<wstring>& standard)
{
return custom.field == standard.field;
return Compare<Protocols>(custom.field, standard.field);
}
inline bool operator==(const BondStruct<wstring>& standard, const WithStaticWString& custom)
template <typename Protocols>
bool Compare(const BondStruct<wstring>& standard, const WithStaticWString& custom)
{
return custom.field == standard.field;
return Compare<Protocols>(custom.field, standard.field);
}
template <typename T>
inline bool operator==(const WithSimpleList<T>& custom, const BondStruct<list<T> >& standard)
template <typename Protocols, typename T>
bool Compare(const WithSimpleList<T>& custom, const BondStruct<list<T> >& standard)
{
return Equal(custom.field, standard.field);
return Equal<Protocols>(custom.field, standard.field);
}
template <typename T>
inline bool operator==(const BondStruct<list<T> >& standard, const WithSimpleList<T>& custom)
template <typename Protocols, typename T>
bool Compare(const BondStruct<list<T> >& standard, const WithSimpleList<T>& custom)
{
return Equal(custom.field, standard.field);
return Equal<Protocols>(custom.field, standard.field);
}
} // namespace unittest
template <typename Reader, typename Writer>
struct SimpleListTest

Просмотреть файл

@ -3,23 +3,33 @@
#include "serialization_test.h"
template <uint16_t N, typename Reader, typename Writer>
template <uint16_t N, typename Reader, typename Writer, typename Protocols>
void CustomProtocolsTests(const char* name)
{
UnitTestSuite suite(name);
AddTestCase<TEST_ID(N),
AllBindingAndMapping1, Reader, Writer, TestReaderStruct>(suite, "Simple struct");
#if !defined(_MSC_VER) || _MSC_VER >= 1900
AllBindingAndMapping1,
#else
AllBindingAndMapping1_CustomProtocols,
#endif
Reader, Writer, TestReaderStruct, Protocols>(suite, "Simple struct");
}
template <uint16_t N, typename Reader, typename Writer>
template <uint16_t N, typename Reader, typename Writer, typename Protocols>
void CustomInputBufferTests(const char* name)
{
UnitTestSuite suite(name);
AddTestCase<TEST_ID(N),
AllBindingAndMapping2, Reader, Writer, NestedStruct1, NestedStruct1OptionalBondedView>(suite, "Optional bonded field");
#if !defined(_MSC_VER) || _MSC_VER >= 1900
AllBindingAndMapping2,
#else
AllBindingAndMapping2_CustomProtocols,
#endif
Reader, Writer, NestedStruct1, NestedStruct1OptionalBondedView, Protocols>(suite, "Optional bonded field");
}
@ -29,12 +39,14 @@ void CustomProtocolsTestsInit()
CustomProtocolsTests<
0x2102,
unit_test::TestReader<bond::InputBuffer>,
unit_test::TestWriter<bond::OutputBuffer> >("Custom protocol TestReader");
unit_test::TestWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<unit_test::TestReader<bond::InputBuffer> > >("Custom protocol TestReader");
CustomInputBufferTests<
0x2103,
unit_test::TestReader<unit_test::CustomInputBuffer>,
unit_test::TestWriter<bond::OutputBuffer> >("Custom protocol TestReader using CustomInputBuffer");
unit_test::TestWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<unit_test::TestReader<unit_test::CustomInputBuffer> > >("Custom protocol TestReader using CustomInputBuffer");
);
}

Просмотреть файл

@ -1,12 +1,10 @@
#pragma once
#include <bond/core/customize.h>
#include <bond/core/protocol.h>
#include <bond/protocol/compact_binary.h>
#include <bond/stream/input_buffer.h>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/list.hpp>
#include "untagged_protocol.h"
@ -128,31 +126,8 @@ namespace unit_test
namespace bond
{
// Add TestReader to the list of protocols used by Bond
template <> struct
customize<protocols>
{
template <typename T> struct
modify
{
typedef typename boost::mpl::joint_view<
boost::mpl::list<
unit_test::TestReader<InputBuffer>,
unit_test::TestReader<unit_test::CustomInputBuffer>,
UntaggedProtocolReader<InputBuffer>
>::type,
T
>::type type;
};
};
BOND_DEFINE_BUFFER_MAGIC(unit_test::CustomInputBuffer, 0x4243 /*CB*/);
// Protocols are disabled by default and we leave TestReader disabled
// and enable it only in custom_protocol.cpp and UntaggedProtocolReader
// in pass_through.cpp.
}
namespace bond
{
template <typename Buffer> struct
is_protocol_enabled<UntaggedProtocolReader<Buffer> >
: std::true_type {};

Просмотреть файл

@ -6,26 +6,94 @@
#include <complex>
#include <limits>
#define UT_Equal(x, y) UT_AssertIsTrue(Equal(x, y))
#define UT_Equal_P(x, y, Protocols) UT_AssertIsTrue(Equal<Protocols>(x, y))
#define UT_Equal(x, y) UT_Equal_P(x, y, bond::BuiltInProtocols)
#define UT_Compare_P(x, y, Protocols) UT_AssertIsTrue(Compare<Protocols>(x, y))
#define UT_Compare(x, y) UT_Compare_P(x, y, bond::BuiltInProtocols)
#define UT_NegateCompare_P(x, y, Protocols) UT_AssertIsTrue(!Compare<Protocols>(x, y))
#define UT_NegateCompare(x, y) UT_NegateCompare_P(x, y, bond::BuiltInProtocols)
template <typename T1, typename T2>
bool operator==(const SkipStruct<T1>& left, const SkipStruct<T2>& right);
template <typename Protocols, typename T1, typename T2>
bool Compare(const SkipStruct<T1>& left, const SkipStruct<T2>& right);
template <typename T>
bool operator==(const SkipStruct<T>& left, const SkipStruct2<T>& right);
template <typename Protocols, typename T>
bool Compare(const SkipStruct<T>& left, const SkipStruct2<T>& right);
template <typename T1, typename T2>
bool operator==(const BondStruct<T1>& left, const BondStruct<T2>& right);
template <typename Protocols, typename T1, typename T2>
bool Compare(const BondStruct<T1>& left, const BondStruct<T2>& right);
template <typename T1, typename T2>
template <typename Protocols, typename NestedStruct1>
bool Compare(const NestedStruct1& left, const NestedStruct1OptionalBondedView& right);
template <typename Protocols>
bool Compare(const NestedStruct1& left, const NestedStruct1BondedView& right);
template <typename Protocols>
bool Compare(const SimpleStruct& left, const SimpleStructView& right);
template <typename Protocols>
bool Compare(const NestedStruct& left, const NestedStructView& right);
template <typename Protocols, typename T>
bool Compare(const WithSimpleList<T>& custom, const BondStruct<std::list<T> >& standard);
template <typename Protocols, typename T>
bool Compare(const BondStruct<std::list<T> >& standard, const WithSimpleList<T>& custom);
template <typename Protocols>
bool Compare(const WithStaticString& custom, const BondStruct<std::string>& standard);
template <typename Protocols>
bool Compare(const BondStruct<std::string>& standard, const WithStaticString& custom);
template <typename Protocols>
bool Compare(const WithStaticWString& custom, const BondStruct<std::wstring>& standard);
template <typename Protocols>
bool Compare(const BondStruct<std::wstring>& standard, const WithStaticWString& custom);
template <typename Protocols>
bool Compare(const StructWithBase& left, const StructWithBaseView& right);
template <typename Protocols>
bool Compare(const SimpleBase& left, const SimpleBaseView& right);
template <typename Protocols>
bool Compare(const NestedWithBase& left, const NestedWithBaseView& right);
template <typename Protocols>
bool Compare(const ListWithBase& left, const ListWithBaseView& right);
template <typename Protocols>
bool Compare(const StructWithBase& left, const SimpleStruct& right);
template <typename Protocols>
bool Compare(const StructWithBase& left, const SimpleBase& right);
template <typename Protocols>
bool Compare(const ListWithBase& left, const ListOfBase& right);
template <typename Protocols>
bool Compare(const NestedWithBase& left, const NestedWithBase2& right);
template <typename Protocols>
bool Compare(const SimpleListsStruct& left, const SimpleListsStructView& right);
template <typename Protocols>
bool Compare(const NestedListsStruct& left, const NestedListsStructView& right);
template <typename Protocols>
bool Compare(const Required& left, const RequiredViewGood& right);
template <typename Protocols, typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
Equal(const T1& lhs, const T2& rhs);
template <typename T>
class Compare
template <typename T, typename Protocols>
class Comparer
{
public:
Compare(const T& left, const T& right, bool& equal)
Comparer(const T& left, const T& right, bool& equal)
: left(left),
right(right),
equal(equal)
@ -35,7 +103,7 @@ public:
void operator()(const Field&);
private:
Compare& operator=(const Compare&);
Comparer& operator=(const Comparer&);
const T& left;
const T& right;
@ -43,102 +111,112 @@ private:
};
inline bool Equal(double left, double right)
{
const int ulp = 5;
return std::abs(left - right) <= std::numeric_limits<double>::epsilon() * (std::max)(std::abs(left), std::abs(right)) * ulp;
}
inline bool Equal(const bond::blob& lhs, const bond::blob& rhs)
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Compare(const T1& lhs, const T2& rhs)
{
return lhs == rhs;
}
template <typename T>
template <typename Protocols = bond::BuiltInProtocols, typename T>
inline typename boost::enable_if<std::is_floating_point<T>, bool>::type
Equal(T left, T right)
{
const int ulp = 5;
return std::abs(left - right) <= std::numeric_limits<T>::epsilon() * (std::max)(std::abs(left), std::abs(right)) * ulp;
}
template <typename Protocols = bond::BuiltInProtocols>
inline bool Equal(const bond::blob& lhs, const bond::blob& rhs)
{
return Compare<Protocols>(lhs, rhs);
}
template <typename Protocols = bond::BuiltInProtocols, typename T>
typename boost::enable_if<bond::has_schema<T>, bool>::type
Equal(const T& left, const T& right)
{
bool equal = true;
boost::mpl::for_each<typename T::Schema::fields>(Compare<T>(left, right, equal));
boost::mpl::for_each<typename T::Schema::fields>(Comparer<T, Protocols>(left, right, equal));
return equal;
}
// "loose" equality for matching but different types
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
typename boost::enable_if<bond::is_basic_type<T1>, bool>::type
Equal(const T1& lhs, const T2& rhs)
{
return bond::cast<T2>(lhs) == rhs;
return Compare<Protocols>(bond::cast<T2>(lhs), rhs);
}
// "loose" equality for struct just calls ==
template <typename T1, typename T2>
// "loose" equality for struct just calls Compare
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
typename boost::enable_if_c<bond::has_schema<T1>::value
&& bond::has_schema<T2>::value, bool>::type
Equal(const T1& lhs, const T2& rhs)
{
return lhs == rhs;
return Compare<Protocols>(lhs, rhs);
}
// "loose" equality for T and bonded<T>
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Equal(const T1& lhs, const bond::bonded<T2>& rhs)
{
T2 rhs_value;
rhs.Deserialize(rhs_value);
rhs.template Deserialize<Protocols>(rhs_value);
return Equal(lhs, rhs_value);
return Equal<Protocols>(lhs, rhs_value);
}
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Equal(const bond::bonded<T1>& lhs, const T2& rhs)
{
T1 lhs_value;
lhs.Deserialize(lhs_value);
lhs.template Deserialize<Protocols>(lhs_value);
return Equal(lhs_value, rhs);
return Equal<Protocols>(lhs_value, rhs);
}
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Equal(const bond::bonded<T1>& lhs, const bond::bonded<T2>& rhs)
{
T1 lhs_value;
lhs.Deserialize(lhs_value);
lhs.template Deserialize<Protocols>(lhs_value);
T2 rhs_value;
rhs.Deserialize(rhs_value);
rhs.template Deserialize<Protocols>(rhs_value);
return Equal(lhs_value, rhs_value);
return Equal<Protocols>(lhs_value, rhs_value);
}
// "loose" equality for pairs
template <typename T1, typename T2, typename T3, typename T4>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2, typename T3, typename T4>
bool Equal(const std::pair<T1, T2>& p1, const std::pair<T3, T4>& p2)
{
return Equal(p1.first, p2.first) && Equal(p1.second, p2.second);
return Equal<Protocols>(p1.first, p2.first) && Equal<Protocols>(p1.second, p2.second);
}
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Equal(const std::pair<T1, T2>& p1, const std::pair<T1, T2>& p2)
{
return Equal(p1.first, p2.first) && Equal(p1.second, p2.second);
return Equal<Protocols>(p1.first, p2.first) && Equal<Protocols>(p1.second, p2.second);
}
// "loose" equality for lists of matching but different types
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
Equal(const T1& lhs, const T2& rhs)
{
@ -150,7 +228,7 @@ Equal(const T1& lhs, const T2& rhs)
while (lhs_items.more() && rhs_items.more())
{
if (!Equal(lhs_items.next(), rhs_items.next()))
if (!Equal<Protocols>(lhs_items.next(), rhs_items.next()))
return false;
}
@ -158,6 +236,7 @@ Equal(const T1& lhs, const T2& rhs)
}
template <typename Protocols = bond::BuiltInProtocols>
inline bool Equal(const bond::blob& lhs, const std::vector<int8_t>& rhs)
{
return (lhs.length() == rhs.size() && rhs.size() == 0)
@ -165,6 +244,7 @@ inline bool Equal(const bond::blob& lhs, const std::vector<int8_t>& rhs)
}
template <typename Protocols = bond::BuiltInProtocols>
inline bool Equal(const std::vector<int8_t>& lhs, const bond::blob& rhs)
{
return (rhs.length() == lhs.size() && lhs.size() == 0)
@ -172,17 +252,17 @@ inline bool Equal(const std::vector<int8_t>& lhs, const bond::blob& rhs)
}
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
typename boost::enable_if_c<bond::has_base<T1>::value
&& bond::has_base<T2>::value, bool>::type
BaseIsEqual(const T1& left, const T2& right)
{
return Equal(static_cast<const typename T1::Schema::base&>(left),
static_cast<const typename T2::Schema::base&>(right));
return Equal<Protocols>(static_cast<const typename T1::Schema::base&>(left),
static_cast<const typename T2::Schema::base&>(right));
}
template <typename T1, typename T2>
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
typename boost::disable_if_c<bond::has_base<T1>::value
|| bond::has_base<T2>::value, bool>::type
BaseIsEqual(const T1& /*left*/, const T2& /*right*/)
@ -191,84 +271,65 @@ BaseIsEqual(const T1& /*left*/, const T2& /*right*/)
}
template <typename T1, typename T2>
bool operator==(const BondStruct<T1>& left, const BondStruct<T2>& right)
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Compare(const BondStruct<T1>& left, const BondStruct<T2>& right)
{
return Equal(left.field, right.field);
}
template <typename T1, typename T2>
bool operator!=(const BondStruct<T1>& left, const BondStruct<T2>& right)
{
return !(left == right);
return Equal<Protocols>(left.field, right.field);
}
template <typename Protocols>
inline bool all_empty(const bond::blob& x, bool root = false)
{
return x.empty() && root;
}
template <typename T>
template <typename Protocols, typename T>
typename boost::disable_if<bond::is_container<T>, bool>::type
all_empty(const T& x, bool root = false)
{
return x == T() && root;
return Compare<Protocols>(x, T()) && root;
}
template <typename T1, typename T2>
template <typename Protocols, typename T1, typename T2>
inline bool all_empty(const std::pair<T1, T2>& x)
{
return all_empty(x.second);
return all_empty<Protocols>(x.second);
}
template <typename T>
template <typename Protocols, typename T>
typename boost::enable_if<bond::is_container<T>, bool>::type
all_empty(const T& x, bool = false)
{
if (!x.empty())
for (bond::const_enumerator<T> items(x); items.more();)
if (!all_empty(items.next()))
if (!all_empty<Protocols>(items.next()))
return false;
return true;
}
template <typename T1, typename T2>
bool operator==(const SkipStruct<T1>& left, const SkipStruct<T2>& right)
template <typename Protocols = bond::BuiltInProtocols, typename T1, typename T2>
bool Compare(const SkipStruct<T1>& left, const SkipStruct<T2>& right)
{
UT_AssertIsTrue(all_empty(right.field1, true));
return left.field2 == right.field2;
UT_AssertIsTrue(all_empty<Protocols>(right.field1, true));
return Compare<Protocols>(left.field2, right.field2);
}
template <typename T1, typename T2>
bool operator!=(const SkipStruct<T1>& left, const SkipStruct<T2>& right)
template <typename Protocols = bond::BuiltInProtocols, typename T>
bool Compare(const SkipStruct<T>& left, const SkipStruct2<T>& right)
{
return !(left == right);
return Equal<Protocols>(left.field2, right.field2);
}
template <typename T>
bool operator==(const SkipStruct<T>& left, const SkipStruct2<T>& right)
{
return left.field2 == right.field2;
}
template <typename T>
bool operator!=(const SkipStruct<T>& left, const SkipStruct2<T>& right)
{
return !(left == right);
}
template <typename T>
template <typename T, typename Protocols>
template <typename Field>
void Compare<T>::operator()(const Field&)
void Comparer<T, Protocols>::operator()(const Field&)
{
equal = equal && Equal(Field::GetVariable(left), Field::GetVariable(right));
equal = equal && Equal<Protocols>(Field::GetVariable(left), Field::GetVariable(right));
}

Просмотреть файл

@ -259,7 +259,7 @@ TEST_CASE_BEGIN(TransformException)
typename Writer::Buffer buffer(4096);
Factory<Writer>::Call(buffer, bond::v1, boost::bind(
bond::Serialize<T, Writer>, InitRandom<T>(2, 2), _1));
bond::Serialize<bond::BuiltInProtocols, T, Writer>, InitRandom<T>(2, 2), _1));
{
for (int i = 0;; ++i)

Просмотреть файл

@ -1,16 +1,13 @@
#include "precompiled.h"
#include "serialization_test.h"
namespace unittest
{
inline bool operator==(const ListWithBase& left, const ListOfBase& right)
template <typename Protocols>
bool Compare(const ListWithBase& left, const ListOfBase& right)
{
return Equal(left.l1, right.l1)
&& Equal(left.vl2, right.vl2)
&& Equal(left.v4, right.v4);
}
return Equal<Protocols>(left.l1, right.l1)
&& Equal<Protocols>(left.vl2, right.vl2)
&& Equal<Protocols>(left.v4, right.v4);
}
template <uint16_t N, typename Reader, typename Writer>

Просмотреть файл

@ -73,7 +73,7 @@ TEST_CASE_BEGIN(StreamDeserializationTest)
T record = InitRandom<T>();
stream.Deserialize(record);
UT_AssertIsTrue(Equal(from[i], record));
UT_Equal(from[i], record);
}
}
@ -86,14 +86,14 @@ TEST_CASE_BEGIN(StreamDeserializationTest)
r2 = InitRandom<T>();
Deserialize(reader, r1);
Deserialize(reader, r2);
UT_AssertIsTrue(Equal(r1, r2));
UT_Equal(r1, r2);
bond::bonded<T> bonded(reader);
r1 = InitRandom<T>();
r2 = InitRandom<T>();
bonded.Deserialize(r1);
bonded.Deserialize(r2);
UT_AssertIsTrue(Equal(r1, r2));
UT_Equal(r1, r2);
}
}
TEST_CASE_END
@ -139,7 +139,7 @@ void StreamTranscoding(uint16_t version = bond::v1)
Record record = InitRandom<Record>();
stream.Deserialize(record);
UT_AssertIsTrue(Equal(records[i], record));
UT_Equal(records[i], record);
}
}

Просмотреть файл

@ -1,35 +1,33 @@
#include "precompiled.h"
#include "serialization_test.h"
namespace unittest
{
bool operator==(const SimpleListsStruct& left, const SimpleListsStructView& right)
template <typename Protocols>
bool Compare(const SimpleListsStruct& left, const SimpleListsStructView& right)
{
return left.l_bool == right.l_bool
&& left.l_int64 == right.l_int64
&& left.l_float == right.l_float
&& left.l_string == right.l_string
&& left.v_int16 == right.v_int16
&& Equal(left.v_double, right.v_double)
&& left.v_string == right.v_string
&& left.s_uint64 == right.s_uint64
&& left.s_string == right.s_string
&& left.m_int8_string == right.m_int8_string
&& left.m_string_bool == right.m_string_bool;
return Compare<Protocols>(left.l_bool, right.l_bool)
&& Compare<Protocols>(left.l_int64, right.l_int64)
&& Compare<Protocols>(left.l_float, right.l_float)
&& Compare<Protocols>(left.l_string, right.l_string)
&& Compare<Protocols>(left.v_int16, right.v_int16)
&& Equal<Protocols>(left.v_double, right.v_double)
&& Compare<Protocols>(left.v_string, right.v_string)
&& Compare<Protocols>(left.s_uint64, right.s_uint64)
&& Compare<Protocols>(left.s_string, right.s_string)
&& Compare<Protocols>(left.m_int8_string, right.m_int8_string)
&& Compare<Protocols>(left.m_string_bool, right.m_string_bool);
}
bool operator==(const NestedListsStruct& left, const NestedListsStructView& right)
template <typename Protocols>
bool Compare(const NestedListsStruct& left, const NestedListsStructView& right)
{
return Equal(left.SLS, right.SLS)
&& Equal(left.vlSLS, right.vlSLS)
&& Equal(left.vvNS, right.vvNS)
&& left.lsb == right.lsb
&& Equal(left.vmds, right.vmds);
return Equal<Protocols>(left.SLS, right.SLS)
&& Equal<Protocols>(left.vlSLS, right.vlSLS)
&& Equal<Protocols>(left.vvNS, right.vvNS)
&& Compare<Protocols>(left.lsb, right.lsb)
&& Equal<Protocols>(left.vmds, right.vmds);
}
} // namespace unittest
template <uint16_t N, typename Reader, typename Writer>
void SimpleListTests(const char* name)

Просмотреть файл

@ -9,16 +9,16 @@ void MarshalingTest(uint16_t version = bond::v1)
typename Writer::Buffer output_buffer;
Factory<Writer>::Call(output_buffer, version, boost::bind(
bond::Marshal<T, Writer>, from, _1));
bond::Marshal<bond::BuiltInProtocols, T, Writer>, from, _1));
T to;
bond::InputBuffer input(output_buffer.GetBuffer());
bond::Unmarshal(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
auto to2 = bond::Unmarshal<T>(input);
UT_AssertIsTrue(from == to2);
UT_Compare(from, to2);
}
@ -38,7 +38,7 @@ void TranscodingTest(uint16_t version = bond::v1)
typename Writer::Buffer output_buffer;
Factory<Writer>::Call(output_buffer, version, boost::bind(
bond::Marshal<T, Writer>, from, _1));
bond::Marshal<bond::BuiltInProtocols, T, Writer>, from, _1));
// Trans-marshal to Simple Protocol using runtime schema
bond::OutputBuffer simple_buffer;
@ -58,7 +58,7 @@ void TranscodingTest(uint16_t version = bond::v1)
{
bond::InputBuffer input(simple_buffer.GetBuffer());
Factory<Writer>::Call(writer_buffer, version, boost::bind(
bond::SelectProtocolAndApply<T, bond::InputBuffer, bond::Marshaler<Writer> >, input, boost::bind(bond::MarshalTo<Writer>, _1)));
bond::SelectProtocolAndApply<T, bond::BuiltInProtocols, bond::InputBuffer, bond::Marshaler<Writer> >, input, boost::bind(bond::MarshalTo<bond::BuiltInProtocols, Writer>, _1)));
}
T to;
@ -66,7 +66,7 @@ void TranscodingTest(uint16_t version = bond::v1)
bond::InputBuffer input(writer_buffer.GetBuffer());
Unmarshal(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
@ -76,7 +76,7 @@ void TranscodingTest(uint16_t version = bond::v1)
{
bond::InputBuffer input(simple_buffer.GetBuffer());
Factory<Writer>::Call(writer_buffer, version, boost::bind(
bond::SelectProtocolAndApply<bond::InputBuffer, bond::Marshaler<Writer> >, bond::GetRuntimeSchema<T>(), input, boost::bind(bond::MarshalTo<Writer>, _1)));
bond::SelectProtocolAndApply<bond::BuiltInProtocols, bond::InputBuffer, bond::Marshaler<Writer> >, bond::GetRuntimeSchema<T>(), input, boost::bind(bond::MarshalTo<bond::BuiltInProtocols, Writer>, _1)));
}
T to;
@ -84,7 +84,7 @@ void TranscodingTest(uint16_t version = bond::v1)
bond::InputBuffer input(writer_buffer.GetBuffer());
Unmarshal(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
@ -118,7 +118,7 @@ TEST_CASE_BEGIN(MapTo)
bond::InputBuffer input(output_buffer.GetBuffer());
bond::SelectProtocolAndApply<From>(input, bond::MapTo<To>(to, mappings));
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
// Mapping with runtime time schema
@ -128,7 +128,7 @@ TEST_CASE_BEGIN(MapTo)
bond::InputBuffer input(output_buffer.GetBuffer());
bond::SelectProtocolAndApply(bond::GetRuntimeSchema<From>(), input, bond::MapTo<To>(to, mappings));
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
TEST_CASE_END

Просмотреть файл

@ -45,8 +45,8 @@ TEST_CASE_BEGIN(DontOmit)
Reader reader(input);
Deserialize(reader, to);
UT_AssertIsTrue(from.field1 == to.field1);
UT_AssertIsTrue(from.field2 == to.field2);
UT_Compare(from.field1, to.field1);
UT_Compare(from.field2, to.field2);
}
TEST_CASE_END

Просмотреть файл

@ -6,15 +6,176 @@
#include "serialization_test.h"
template <typename Reader, typename Writer, typename Payload, typename T>
void Merging(Payload payload, const T& obj, uint16_t version = bond::v1, bool mergeByDeserialize = true)
template <typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols, typename Payload, typename T>
void Merging(Payload payload, const T& obj, uint16_t version = bond::v1, bool mergeByDeserialize = true);
template <typename Reader, typename Writer, typename Payload, typename T, typename Protocols = bond::BuiltInProtocols>
void MergingRandom()
{
Reader merged = Merge<Reader, Writer>(payload, obj, version);
// random values
for (uint32_t i = 0; i < c_iterations; ++i)
{
Merging<Reader, Writer, Protocols>(InitRandom<Payload, Protocols>(), InitRandom<T, Protocols>());
Merging<Reader, Writer, Protocols>(InitRandom<Payload, Protocols>(), InitRandom<T, Protocols>(), Reader::version);
}
}
template <typename Reader, typename Writer, typename Payload, typename T, typename Protocols = bond::BuiltInProtocols>
void AllMerging()
{
// default value
Merging<Reader, Writer, Protocols>(Payload(), T());
Merging<Reader, Writer, Protocols>(Payload(), T(), Reader::version);
Merging<Reader, Writer, Protocols>(InitRandom<Payload, Protocols>(), T());
Merging<Reader, Writer, Protocols>(InitRandom<Payload, Protocols>(), T(), Reader::version);
Merging<Reader, Writer, Protocols>(Payload(), InitRandom<T, Protocols>());
Merging<Reader, Writer, Protocols>(Payload(), InitRandom<T, Protocols>(), Reader::version);
// random values
MergingRandom<Reader, Writer, Payload, T, Protocols>();
}
namespace unittest
{
template <typename Protocols, typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1& payload, const T1& merged, const T2& obj);
template <typename Protocols, typename T1, typename T2>
typename boost::disable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1&, const T1&, const T2&)
{
return false;
}
template <typename Protocols, typename P, typename T1, typename T2, typename T3, typename T4>
bool MergedEqual(bond::const_enumerator<P>&, const P& map, const std::pair<T1, T2>& p1, const std::pair<T3, T4>& p2)
{
if (!Equal<Protocols>(p1.first, p2.first))
return false;
if (map.end() != map.find(p1.first))
return MergedEqual<Protocols>(map.find(p1.first)->second, p1.second, p2.second);
else
return MergedEqual<Protocols>(typename bond::element_type<P>::type::second_type(), p1.second, p2.second);
}
template <typename Protocols, typename P, typename T1, typename T2>
bool MergedEqual(bond::const_enumerator<P>& items, const P&, const T1& i1, const T2& i2)
{
if (items.more())
return MergedEqual<Protocols>(items.next(), i1, i2);
else
return MergedEqual<Protocols>(typename bond::element_type<P>::type(), i1, i2);
}
template <typename Protocols, typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1& payload, const T1& merged, const T2& obj)
{
if (container_size(obj) != container_size(merged))
return false;
bond::const_enumerator<T1> payload_items(payload);
bond::const_enumerator<T1> merged_items(merged);
bond::const_enumerator<T2> obj_items(obj);
while (merged_items.more())
if (!MergedEqual<Protocols>(payload_items, payload, merged_items.next(), obj_items.next()))
return false;
return true;
}
template <typename Protocols>
bool MergedEqual(const SimpleListsStruct& payload, const SimpleListsStruct& merged, const SimpleListsStructView& obj)
{
return Compare<Protocols>(merged.l_bool, obj.l_bool)
&& Compare<Protocols>(merged.l_int64, obj.l_int64)
&& Compare<Protocols>(merged.l_float, obj.l_float)
&& Compare<Protocols>(merged.l_string, obj.l_string)
&& Compare<Protocols>(merged.v_int16, obj.v_int16)
&& Compare<Protocols>(merged.v_double, obj.v_double)
&& Compare<Protocols>(merged.v_string, obj.v_string)
&& Compare<Protocols>(merged.s_uint64, obj.s_uint64)
&& Compare<Protocols>(merged.s_string, obj.s_string)
&& Compare<Protocols>(merged.m_int8_string, obj.m_int8_string)
&& Compare<Protocols>(merged.m_string_bool, obj.m_string_bool)
&& Compare<Protocols>(merged.l_uint32, payload.l_uint32)
&& Compare<Protocols>(merged.l_int16, payload.l_int16)
&& Compare<Protocols>(merged.v_bool, payload.v_bool)
&& Compare<Protocols>(merged.v_uint8, payload.v_uint8)
&& Compare<Protocols>(merged.v_int64, payload.v_int64)
&& Compare<Protocols>(merged.s_bool, payload.s_bool)
&& Compare<Protocols>(merged.s_float, payload.s_float)
&& Compare<Protocols>(merged.m_float_uint16, payload.m_float_uint16);
}
template <typename Protocols>
bool MergedEqual(const NestedStruct& payload, const NestedStruct& merged, const NestedStructView& obj)
{
return Compare<Protocols>(merged.m_int8, obj.m_int8)
&& Compare<Protocols>(merged.n1, obj.n1)
&& Compare<Protocols>(merged.m_int16, obj.m_int16)
&& Compare<Protocols>(merged.n3, payload.n3)
&& Compare<Protocols>(merged.m_bool, payload.m_bool)
&& Compare<Protocols>(merged.n2, payload.n2)
&& Compare<Protocols>(merged.m_int32, payload.m_int32)
&& Compare<Protocols>(merged.m_int64, payload.m_int64)
&& Compare<Protocols>(merged.m_uint8, payload.m_uint8)
&& Compare<Protocols>(merged.m_uint16, payload.m_uint16)
&& Compare<Protocols>(merged.m_uint32, payload.m_uint32)
&& Compare<Protocols>(merged.m_uint64, payload.m_uint64)
&& Compare<Protocols>(merged.m_double, payload.m_double)
&& Compare<Protocols>(merged.m_float, payload.m_float)
&& Compare<Protocols>(merged.m_enum1, payload.m_enum1)
&& Compare<Protocols>(merged.m_str, payload.m_str);
}
template <typename Protocols>
bool MergedEqual(const NestedMaps& payload, const NestedMaps& merged, const NestedMapsView& obj)
{
return Equal<Protocols>(payload.m64ls, merged.m64ls)
&& MergedEqual<Protocols>(payload.msSLS, merged.msSLS, obj.msSLS)
&& MergedEqual<Protocols>(payload.m32lNS, merged.m32lNS, obj.m32lNS);
}
template <typename Protocols>
bool MergedEqual(const NestedListsStruct& payload, const NestedListsStruct& merged, const NestedListsView& obj)
{
return Equal<Protocols>(payload.ll8, merged.ll8)
&& Equal<Protocols>(payload.lvls, merged.lvls)
&& Equal<Protocols>(payload.SLS, merged.SLS)
&& Equal<Protocols>(payload.vf, merged.vf)
&& Equal<Protocols>(payload.vss, merged.vss)
&& Equal<Protocols>(payload.lsb, merged.lsb)
&& Equal<Protocols>(payload.m64ls, merged.m64ls)
&& Equal<Protocols>(payload.vmds, merged.vmds)
&& MergedEqual<Protocols>(payload.lSLS, merged.lSLS, obj.lSLS)
&& MergedEqual<Protocols>(payload.vlSLS, merged.vlSLS, obj.vlSLS)
&& MergedEqual<Protocols>(payload.vvNS, merged.vvNS, obj.vvNS);
}
} // namespace unittest
template <typename Reader, typename Writer, typename Protocols, typename Payload, typename T>
void Merging(Payload payload, const T& obj, uint16_t version, bool mergeByDeserialize)
{
Reader merged = Merge<Reader, Writer, Protocols>(payload, obj, version);
// Deserialize merged into T and compare against obj
{
T to;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
@ -25,13 +186,13 @@ void Merging(Payload payload, const T& obj, uint16_t version = bond::v1, bool me
#endif
{
to = InitRandom<T>();
to = InitRandom<T, Protocols>();
Fixup(to);
}
Deserialize(merged, to);
bond::Deserialize<Protocols>(merged, to);
UT_AssertIsTrue(Equal(obj, to));
UT_Equal_P(obj, to, Protocols);
}
// Deserialize merged into Payload and compare against combination of the
@ -48,185 +209,28 @@ void Merging(Payload payload, const T& obj, uint16_t version = bond::v1, bool me
#pragma warning(pop)
#endif
{
to = InitRandom<Payload>();
to = InitRandom<Payload, Protocols>();
Fixup(to);
}
Deserialize(merged, to);
bond::Deserialize<Protocols>(merged, to);
if (mergeByDeserialize)
{
// Will fail an assert without
// #define BOND_UNIT_TEST_ONLY_PERMIT_OBJECT_REUSE
Deserialize(Serialize<Reader, Writer>(obj, version), payload);
bond::Deserialize<Protocols>(Serialize<Reader, Writer, Protocols>(obj, version), payload);
UT_AssertIsTrue(Equal(payload, to));
UT_Equal_P(payload, to, Protocols);
}
else
{
UT_AssertIsTrue(MergedEqual(payload, to, obj));
UT_AssertIsTrue(unittest::MergedEqual<Protocols>(payload, to, obj));
}
}
}
template <typename Reader, typename Writer, typename Payload, typename T>
void MergingRandom()
{
// random values
for (uint32_t i = 0; i < c_iterations; ++i)
{
Merging<Reader, Writer>(InitRandom<Payload>(), InitRandom<T>());
Merging<Reader, Writer>(InitRandom<Payload>(), InitRandom<T>(), Reader::version);
}
}
template <typename Reader, typename Writer, typename Payload, typename T>
void AllMerging()
{
// default value
Merging<Reader, Writer>(Payload(), T());
Merging<Reader, Writer>(Payload(), T(), Reader::version);
Merging<Reader, Writer>(InitRandom<Payload>(), T());
Merging<Reader, Writer>(InitRandom<Payload>(), T(), Reader::version);
Merging<Reader, Writer>(Payload(), InitRandom<T>());
Merging<Reader, Writer>(Payload(), InitRandom<T>(), Reader::version);
// random values
MergingRandom<Reader, Writer, Payload, T>();
}
namespace unittest
{
template <typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1& payload, const T1& merged, const T2& obj);
template <typename T1, typename T2>
typename boost::disable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1&, const T1&, const T2&)
{
return false;
}
template <typename P, typename T1, typename T2, typename T3, typename T4>
bool MergedEqual(bond::const_enumerator<P>&, const P& map, const std::pair<T1, T2>& p1, const std::pair<T3, T4>& p2)
{
if (!Equal(p1.first, p2.first))
return false;
if (map.end() != map.find(p1.first))
return MergedEqual(map.find(p1.first)->second, p1.second, p2.second);
else
return MergedEqual(typename bond::element_type<P>::type::second_type(), p1.second, p2.second);
}
template <typename P, typename T1, typename T2>
bool MergedEqual(bond::const_enumerator<P>& items, const P&, const T1& i1, const T2& i2)
{
if (items.more())
return MergedEqual(items.next(), i1, i2);
else
return MergedEqual(typename bond::element_type<P>::type(), i1, i2);
}
template <typename T1, typename T2>
typename boost::enable_if<bond::is_container<T1>, bool>::type
MergedEqual(const T1& payload, const T1& merged, const T2& obj)
{
if (container_size(obj) != container_size(merged))
return false;
bond::const_enumerator<T1> payload_items(payload);
bond::const_enumerator<T1> merged_items(merged);
bond::const_enumerator<T2> obj_items(obj);
while (merged_items.more())
if (!MergedEqual(payload_items, payload, merged_items.next(), obj_items.next()))
return false;
return true;
}
bool MergedEqual(const SimpleListsStruct& payload, const SimpleListsStruct& merged, const SimpleListsStructView& obj)
{
return merged.l_bool == obj.l_bool
&& merged.l_int64 == obj.l_int64
&& merged.l_float == obj.l_float
&& merged.l_string == obj.l_string
&& merged.v_int16 == obj.v_int16
&& merged.v_double == obj.v_double
&& merged.v_string == obj.v_string
&& merged.s_uint64 == obj.s_uint64
&& merged.s_string == obj.s_string
&& merged.m_int8_string == obj.m_int8_string
&& merged.m_string_bool == obj.m_string_bool
&& merged.l_uint32 == payload.l_uint32
&& merged.l_int16 == payload.l_int16
&& merged.v_bool == payload.v_bool
&& merged.v_uint8 == payload.v_uint8
&& merged.v_int64 == payload.v_int64
&& merged.s_bool == payload.s_bool
&& merged.s_float == payload.s_float
&& merged.m_float_uint16 == payload.m_float_uint16;
}
bool MergedEqual(const NestedStruct& payload, const NestedStruct& merged, const NestedStructView& obj)
{
return merged.m_int8 == obj.m_int8
&& merged.n1 == obj.n1
&& merged.m_int16 == obj.m_int16
&& merged.n3 == payload.n3
&& merged.m_bool == payload.m_bool
&& merged.n2 == payload.n2
&& merged.m_int32 == payload.m_int32
&& merged.m_int64 == payload.m_int64
&& merged.m_uint8 == payload.m_uint8
&& merged.m_uint16 == payload.m_uint16
&& merged.m_uint32 == payload.m_uint32
&& merged.m_uint64 == payload.m_uint64
&& merged.m_double == payload.m_double
&& merged.m_float == payload.m_float
&& merged.m_enum1 == payload.m_enum1
&& merged.m_str == payload.m_str;
}
bool MergedEqual(const NestedMaps& payload, const NestedMaps& merged, const NestedMapsView& obj)
{
return Equal(payload.m64ls, merged.m64ls)
&& MergedEqual(payload.msSLS, merged.msSLS, obj.msSLS)
&& MergedEqual(payload.m32lNS, merged.m32lNS, obj.m32lNS);
}
bool MergedEqual(const NestedListsStruct& payload, const NestedListsStruct& merged, const NestedListsView& obj)
{
return Equal(payload.ll8, merged.ll8)
&& Equal(payload.lvls, merged.lvls)
&& Equal(payload.SLS, merged.SLS)
&& Equal(payload.vf, merged.vf)
&& Equal(payload.vss, merged.vss)
&& Equal(payload.lsb, merged.lsb)
&& Equal(payload.m64ls, merged.m64ls)
&& Equal(payload.vmds, merged.vmds)
&& MergedEqual(payload.lSLS, merged.lSLS, obj.lSLS)
&& MergedEqual(payload.vlSLS, merged.vlSLS, obj.vlSLS)
&& MergedEqual(payload.vvNS, merged.vvNS, obj.vvNS);
}
} // namespace unittest
class ModifyContainers
: public bond::ModifyingTransform
{

Просмотреть файл

@ -2,47 +2,44 @@
#include "serialization_test.h"
#include "untagged_protocol.h"
namespace unittest
{
// These operator== are quite expensive to compile; they are made into function templates
// These Compare functions are quite expensive to compile; they are made into function templates
// so that the code is not generated when building a single unit test
template <typename NestedStruct>
inline bool operator==(const NestedStruct& left, const NestedStructBondedView& right)
template <typename Protocols, typename NestedStruct>
bool Compare(const NestedStruct& left, const NestedStructBondedView& right)
{
return left.m_bool == right.m_bool
&& left.m_int8 == left.m_int8
&& Equal(left.n3, right.n3)
&& Equal(left.n2, right.n2)
&& Equal(left.n1, right.n1);
return Compare<Protocols>(left.m_bool, right.m_bool)
&& Compare<Protocols>(left.m_int8, left.m_int8)
&& Equal<Protocols>(left.n3, right.n3)
&& Equal<Protocols>(left.n2, right.n2)
&& Equal<Protocols>(left.n1, right.n1);
}
template <typename NestedStruct1>
inline bool operator==(const NestedStruct1& left, const NestedStruct1BondedView& right)
template <typename Protocols>
bool Compare(const NestedStruct1& left, const NestedStruct1BondedView& right)
{
return Equal(left.s, right.s);
return Equal<Protocols>(left.s, right.s);
}
template <typename NestedListsStruct>
inline bool operator==(const NestedListsStruct& left, const NestedListsStructBondedView& right)
template <typename Protocols, typename NestedListsStruct>
bool Compare(const NestedListsStruct& left, const NestedListsStructBondedView& right)
{
return Equal(left.lSLS, right.lSLS)
&& Equal(left.vlSLS, right.vlSLS)
&& Equal(left.vvNS, right.vvNS)
&& Equal(left.m64ls, right.m64ls);
return Equal<Protocols>(left.lSLS, right.lSLS)
&& Equal<Protocols>(left.vlSLS, right.vlSLS)
&& Equal<Protocols>(left.vvNS, right.vvNS)
&& Equal<Protocols>(left.m64ls, right.m64ls);
}
template <typename NestedWithBase1>
inline bool operator==(const NestedWithBase1& left, const NestedWithBase1BondedBaseView& right)
template <typename Protocols, typename NestedWithBase1>
bool Compare(const NestedWithBase1& left, const NestedWithBase1BondedBaseView& right)
{
return Equal(left.s1, right.s1)
&& Equal(left.s2, right.s2);
return Equal<Protocols>(left.s1, right.s1)
&& Equal<Protocols>(left.s2, right.s2);
}
}
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename T, typename Through, typename BondedType>
void PassThrough(uint16_t version = bond::v1)
@ -68,26 +65,26 @@ void PassThrough(uint16_t version = bond::v1)
bonded_to.Deserialize(to);
UT_AssertIsTrue(to == from);
UT_Compare(to, from);
}
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To, typename BondedType>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To, typename BondedType, typename Protocols>
void Transcoding(uint16_t version1 = bond::v1, uint16_t version2 = bond::v1)
{
From from = InitRandom<From>();
From from = InitRandom<From, Protocols>();
// Compile-time schema
{
bond::bonded<BondedType> bonded_from(GetBonded<Reader1, Writer1, BondedType>(from, version1));
bond::bonded<BondedType> bonded_from(GetBonded<Reader1, Writer1, BondedType, Protocols>(from, version1));
bond::bonded<To> bonded_to(GetBonded<Reader2, Writer2, To>(bonded_from, version2));
bond::bonded<To> bonded_to(GetBonded<Reader2, Writer2, To, Protocols>(bonded_from, version2));
To to = InitRandom<To>();
To to = InitRandom<To, Protocols>();
bonded_to.Deserialize(to);
bonded_to.template Deserialize<Protocols>(to);
UT_Equal(from, to);
UT_Equal_P(from, to, Protocols);
}
// Run-time schema
@ -95,15 +92,15 @@ void Transcoding(uint16_t version1 = bond::v1, uint16_t version2 = bond::v1)
bond::bonded<void> bonded_from(GetBonded<Reader1, Writer1,
typename boost::mpl::if_<bond::has_schema<BondedType>,
BondedType,
From>::type>(from, version1));
From>::type, Protocols>(from, version1));
bond::bonded<To> bonded_to(GetBonded<Reader2, Writer2, To>(bonded_from, version2));
bond::bonded<To> bonded_to(GetBonded<Reader2, Writer2, To, Protocols>(bonded_from, version2));
To to = InitRandom<To>();
To to = InitRandom<To, Protocols>();
bonded_to.Deserialize(to);
bonded_to.template Deserialize<Protocols>(to);
UT_Equal(from, to);
UT_Equal_P(from, to, Protocols);
}
}
@ -127,7 +124,7 @@ void BondedSerialize(uint16_t version = bond::v1)
bonded_pass_through.Deserialize(to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
// Run-time schema
@ -138,7 +135,7 @@ void BondedSerialize(uint16_t version = bond::v1)
bonded_pass_through.Deserialize(to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
@ -173,30 +170,30 @@ void AllProtoBondedSerialize()
}
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::disable_if_c<bond::uses_static_parser<Reader1>::value || bond::uses_static_parser<Reader2>::value || std::is_same<Reader2, bond::SimpleJsonReader<typename Reader2::Buffer> >::value>::type
AllTypesTranscoding()
{
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(bond::v1, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(Reader1::version, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly>(Reader1::version, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly, Protocols>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(bond::v1, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(Reader1::version, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly, Protocols>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, ForwardDeclarationOnly, Protocols>(Reader1::version, Reader2::version);
}
// Simple JSON flattens inheritance hierarchy and thus doesn't always supprot transcoding with w/o schema becase
// ordinal used for fields in JSON when names are not available can collide.
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<bond::uses_static_parser<Reader1>::value || bond::uses_static_parser<Reader2>::value || std::is_same<Reader2, bond::SimpleJsonReader<typename Reader2::Buffer> >::value>::type
AllTypesTranscoding()
{
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(bond::v1, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From>(Reader1::version, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>();
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(Reader1::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(bond::v1, Reader2::version);
Transcoding<Reader1, Writer1, Reader2, Writer2, From, To, From, Protocols>(Reader1::version, Reader2::version);
}
@ -263,10 +260,10 @@ TEST_CASE_BEGIN(AllTranscoding)
TEST_CASE_END
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename From, typename To, typename Protocols>
TEST_CASE_BEGIN(TranscodingTest)
{
AllTypesTranscoding<Reader1, Writer1, Reader2, Writer2, From, To>();
AllTypesTranscoding<Reader1, Writer1, Reader2, Writer2, From, To, Protocols>();
}
TEST_CASE_END
@ -301,7 +298,7 @@ TEST_CASE_BEGIN(BasicTypesTranscoding)
NestedStruct1 n1;
NestedStruct1BondedView n2;
UT_AssertIsTrue(n1 == n2);
UT_Compare(n1, n2);
}
TEST_CASE_END
@ -342,12 +339,12 @@ namespace bond
}
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename Bonded, typename T>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename Bonded, typename Protocols, typename T>
void DefaultValuesTranscodingTest(T to, uint16_t version1 = bond::v1, uint16_t version2 = bond::v1)
{
T from;
bond::bonded<Bonded> bonded1(GetBonded<Reader1, Writer1, T>(from, version1));
bond::bonded<Bonded> bonded1(GetBonded<Reader1, Writer1, T, Protocols>(from, version1));
// OutputBuffer is not really designed to allow writing before current pointer
// which is required for our test untagged protocol. However it works if
@ -355,18 +352,18 @@ void DefaultValuesTranscodingTest(T to, uint16_t version1 = bond::v1, uint16_t v
typename Writer2::Buffer output_buffer(4096);
Factory<Writer2>::Call(output_buffer, version2, boost::bind(
&bond::bonded<Bonded>::template Serialize<Writer2>, bonded1, _1));
&bond::bonded<Bonded>::template Serialize<Protocols, Writer2>, bonded1, _1));
typename Reader2::Buffer input_buffer(output_buffer.GetBuffer());
Reader2 input = Factory<Reader2>::Create(input_buffer, version2);
bond::Deserialize(input, to);
bond::Deserialize<Protocols>(input, to);
UT_AssertIsTrue(from == to);
UT_Compare_P(from, to, Protocols);
}
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename Protocols>
TEST_CASE_BEGIN(DefaultValuesTranscoding)
{
typedef OptionalContainers T;
@ -387,23 +384,23 @@ TEST_CASE_BEGIN(DefaultValuesTranscoding)
init = InitRandom<T>();
}
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void>(init);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void>(init, bond::v1, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void>(init, Reader1::version, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void, Protocols>(init);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void, Protocols>(init, bond::v1, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, void, Protocols>(init, Reader1::version, Reader2::version);
}
TEST_CASE_END
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2>
template <typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename Protocols>
TEST_CASE_BEGIN(OmittedDefaultValuesTranscoding)
{
typedef OptionalNothing T;
T init;
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T>(init);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T>(init, bond::v1, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T>(init, Reader1::version, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T, Protocols>(init);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T, Protocols>(init, bond::v1, Reader2::version);
DefaultValuesTranscodingTest<Reader1, Writer1, Reader2, Writer2, T, Protocols>(init, Reader1::version, Reader2::version);
}
TEST_CASE_END
@ -441,7 +438,7 @@ void PassThroughTests(const char* name)
BasicTypesTranscoding, Reader1, Writer1, Reader2, Writer2>(suite, "Transcoding basic types");
AddTestCase<TEST_ID(N),
DefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2>(suite, "Transcoding default values");
DefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2, bond::BuiltInProtocols>(suite, "Transcoding default values");
}
@ -452,20 +449,20 @@ void PassThroughTests(const char* name)
}
template <uint16_t N, typename Reader1, typename Writer1, typename Reader2, typename Writer2>
template <uint16_t N, typename Reader1, typename Writer1, typename Reader2, typename Writer2, typename Protocols = bond::BuiltInProtocols>
void TranscodingTests(const char* name)
{
UnitTestSuite suite(name);
AddTestCase<TEST_ID(N),
TranscodingTest, Reader1, Writer1, Reader2, Writer2,
unittest::NestedWithBase, unittest::NestedWithBase>(suite, "Transcoding with inheritance");
unittest::NestedWithBase, unittest::NestedWithBase, Protocols>(suite, "Transcoding with inheritance");
AddTestCase<TEST_ID(N),
DefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2>(suite, "Transcoding default values");
DefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2, Protocols>(suite, "Transcoding default values");
AddTestCase<TEST_ID(N),
OmittedDefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2>(suite, "Transcoding omitted values");
OmittedDefaultValuesTranscoding, Reader1, Writer1, Reader2, Writer2, Protocols>(suite, "Transcoding omitted values");
}
@ -520,7 +517,8 @@ void PassThroughTestsInit()
bond::CompactBinaryReader<bond::InputBuffer>,
bond::CompactBinaryWriter<bond::OutputBuffer>,
UntaggedProtocolReader<bond::InputBuffer>,
UntaggedProtocolWriter<bond::OutputBuffer> >("CompactBinary-UntaggedProtocol transcoding");
UntaggedProtocolWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<UntaggedProtocolReader<bond::InputBuffer> > >("CompactBinary-UntaggedProtocol transcoding");
);
@ -540,7 +538,8 @@ void PassThroughTestsInit()
UntaggedProtocolReader<bond::InputBuffer>,
UntaggedProtocolWriter<bond::OutputBuffer>,
UntaggedProtocolReader<bond::InputBuffer>,
UntaggedProtocolWriter<bond::OutputBuffer> >("UntaggedProtocol-UntaggedProtocol transcoding");
UntaggedProtocolWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<UntaggedProtocolReader<bond::InputBuffer> > >("UntaggedProtocol-UntaggedProtocol transcoding");
}
bool init_unit_test()

Просмотреть файл

@ -2,33 +2,31 @@
#include "serialization_test.h"
#include "untagged_protocol.h"
namespace unittest
{
inline bool operator==(const Required& left, const RequiredViewGood& right)
template <typename Protocols>
bool Compare(const Required& left, const RequiredViewGood& right)
{
return left.x == right.x
&& Equal(left.x2, right.x2)
&& (uint64_t)left.z2 == right.z2;
return Compare<Protocols>(left.x, right.x)
&& Equal<Protocols>(left.x2, right.x2)
&& Compare<Protocols>((uint64_t)left.z2, right.z2);
}
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols>
void RequiredFieldsTest(const From& from)
{
typename Writer::Buffer buffer(1024);
Writer writer(buffer);
bond::Serialize(from, writer);
bond::Serialize<Protocols>(from, writer);
{
To to;
Reader reader(buffer.GetBuffer());
bond::bonded<From, Reader&> bonded(reader);
bonded.Deserialize(to);
UT_AssertIsTrue(Equal(from, to));
bonded.template Deserialize<Protocols>(to);
UT_Equal(from, to);
}
{
@ -36,35 +34,35 @@ void RequiredFieldsTest(const From& from)
Reader reader(buffer.GetBuffer());
bond::bonded<void, Reader&> bonded(reader, bond::GetRuntimeSchema<From>());
bonded.Deserialize(to);
UT_AssertIsTrue(Equal(from, to));
bonded.template Deserialize<Protocols>(to);
UT_Equal(from, to);
}
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols>
TEST_CASE_BEGIN(RequiredFields)
{
RequiredFieldsTest<Reader, Writer, From, To>(From());
RequiredFieldsTest<Reader, Writer, From, To>(InitRandom<From>());
RequiredFieldsTest<Reader, Writer, From, To, Protocols>(From());
RequiredFieldsTest<Reader, Writer, From, To, Protocols>(InitRandom<From, Protocols>());
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols>
void MissingRequiredFieldsTest(const From& from)
{
typename Writer::Buffer buffer(1024);
Writer writer(buffer);
bond::Serialize(from, writer);
bond::Serialize<Protocols>(from, writer);
{
To to;
Reader reader(buffer.GetBuffer());
bond::bonded<From, Reader&> bonded(reader);
UT_AssertThrows((bonded.Deserialize(to)), bond::CoreException);
UT_AssertThrows((bonded.template Deserialize<Protocols>(to)), bond::CoreException);
}
{
@ -72,21 +70,21 @@ void MissingRequiredFieldsTest(const From& from)
Reader reader(buffer.GetBuffer());
bond::bonded<void, Reader&> bonded(reader, bond::GetRuntimeSchema<From>());
UT_AssertThrows((bonded.Deserialize(to)), bond::CoreException);
UT_AssertThrows((bonded.template Deserialize<Protocols>(to)), bond::CoreException);
}
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols>
TEST_CASE_BEGIN(MissingRequiredFields)
{
MissingRequiredFieldsTest<Reader, Writer, From, To>(From());
MissingRequiredFieldsTest<Reader, Writer, From, To>(InitRandom<From>());
MissingRequiredFieldsTest<Reader, Writer, From, To, Protocols>(From());
MissingRequiredFieldsTest<Reader, Writer, From, To, Protocols>(InitRandom<From, Protocols>());
}
TEST_CASE_END
template <typename Reader, typename Writer, typename T>
template <typename Reader, typename Writer, typename T, typename Protocols>
TEST_CASE_BEGIN(OptionalToRequired)
{
typedef BondStructOptional<T> From;
@ -97,14 +95,14 @@ TEST_CASE_BEGIN(OptionalToRequired)
typename Writer::Buffer buffer(1024);
Factory<Writer>::Call(buffer, bond::v1, boost::bind(
bond::Serialize<From, Writer>, from, _1));
bond::Serialize<Protocols, From, Writer>, from, _1));
{
To to;
Reader reader(buffer.GetBuffer());
bond::bonded<To, Reader&> bonded(reader);
UT_AssertThrows((bonded.Deserialize(to)), bond::CoreException);
UT_AssertThrows((bonded.template Deserialize<Protocols>(to)), bond::CoreException);
}
{
@ -112,48 +110,48 @@ TEST_CASE_BEGIN(OptionalToRequired)
Reader reader(buffer.GetBuffer());
bond::bonded<void, Reader&> bonded(reader, bond::GetRuntimeSchema<To>());
UT_AssertThrows((bonded.Deserialize(to)), bond::CoreException);
UT_AssertThrows((bonded.template Deserialize<Protocols>(to)), bond::CoreException);
}
}
TEST_CASE_END
template <uint16_t N, typename Reader, typename Writer>
template <uint16_t N, typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols>
void RequiredTests(const char* name)
{
UnitTestSuite suite(name);
AddTestCase<TEST_ID(N),
RequiredFields, Reader, Writer, Required, Required>(suite, "Struct with required fields");
RequiredFields, Reader, Writer, Required, Required, Protocols>(suite, "Struct with required fields");
AddTestCase<TEST_ID(N),
RequiredFields, Reader, Writer, Required, RequiredViewGood>(suite, "View with required fields");
RequiredFields, Reader, Writer, Required, RequiredViewGood, Protocols>(suite, "View with required fields");
AddTestCase<TEST_ID(N),
RequiredFields, Reader, Writer, RequiredViewGood, RequiredViewGood>(suite, "Required and optional fields");
RequiredFields, Reader, Writer, RequiredViewGood, RequiredViewGood, Protocols>(suite, "Required and optional fields");
AddTestCase<TEST_ID(N),
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingLast>(suite, "Missing last required field");
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingLast, Protocols>(suite, "Missing last required field");
AddTestCase<TEST_ID(N),
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingFirst>(suite, "Missing first required field");
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingFirst, Protocols>(suite, "Missing first required field");
AddTestCase<TEST_ID(N),
MissingRequiredFields, Reader, Writer, Required, RequiredViewMismatchType>(suite, "Mimatched type required field");
MissingRequiredFields, Reader, Writer, Required, RequiredViewMismatchType, Protocols>(suite, "Mimatched type required field");
AddTestCase<TEST_ID(N),
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingInNested>(suite, "Required in nested fields");
MissingRequiredFields, Reader, Writer, Required, RequiredViewMissingInNested, Protocols>(suite, "Required in nested fields");
AddTestCase<TEST_ID(N),
MissingRequiredFields, Reader, Writer, bond::Void, RequiredViewMissingLast>(suite, "Missing all fields");
MissingRequiredFields, Reader, Writer, bond::Void, RequiredViewMissingLast, Protocols>(suite, "Missing all fields");
if (bond::may_omit_fields<Writer>::value)
{
AddTestCase<TEST_ID(N),
OptionalToRequired, Reader, Writer, bool>(suite, "Optional bool to required");
OptionalToRequired, Reader, Writer, bool, Protocols>(suite, "Optional bool to required");
AddTestCase<TEST_ID(N),
OptionalToRequired, Reader, Writer, list<float> >(suite, "Optional list to required");
OptionalToRequired, Reader, Writer, list<float>, Protocols>(suite, "Optional list to required");
}
}
@ -191,7 +189,8 @@ void RequiredTestsInit()
RequiredTests<
0x1405,
UntaggedProtocolReader<bond::InputBuffer>,
UntaggedProtocolWriter<bond::OutputBuffer> >("Required fields tests for untagged protocol");
UntaggedProtocolWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<UntaggedProtocolReader<bond::InputBuffer> > >("Required fields tests for untagged protocol");
}
bool init_unit_test()

Просмотреть файл

@ -13,6 +13,12 @@ rebind_buffer_by_reference<Reader<Buffer> >
typedef Reader<Buffer&> type;
};
template <template <typename T, typename U> class Reader, typename Buffer, typename MarshaledBondedProtocols> struct
rebind_buffer_by_reference<Reader<Buffer, MarshaledBondedProtocols>>
{
typedef Reader<Buffer&, MarshaledBondedProtocols> type;
};
template <typename Reader, typename Writer, typename T>
TEST_CASE_BEGIN(Streaming)
@ -49,8 +55,8 @@ TEST_CASE_BEGIN(Streaming)
UT_AssertIsTrue(reader.GetBuffer().IsEof());
UT_AssertIsTrue(from1 == to1);
UT_AssertIsTrue(from2 == to2);
UT_Compare(from1, to1);
UT_Compare(from2, to2);
}
{
@ -67,8 +73,8 @@ TEST_CASE_BEGIN(Streaming)
UT_AssertIsTrue(buffer.IsEof());
UT_AssertIsTrue(from1 == to1);
UT_AssertIsTrue(from2 == to2);
UT_Compare(from1, to1);
UT_Compare(from2, to2);
}
}
TEST_CASE_END
@ -94,7 +100,7 @@ untagged_payload_size<bond::no_base>
};
template <typename Reader, typename Writer, typename T>
template <typename Reader, typename Writer, typename T, typename Protocols>
TEST_CASE_BEGIN(DefaultValues)
{
T obj;
@ -106,7 +112,7 @@ TEST_CASE_BEGIN(DefaultValues)
Writer output(output_buffer);
// serialize value to output
bond::Serialize(obj, output);
bond::Serialize<Protocols>(obj, output);
if (bond::uses_dynamic_parser<Reader>::value)
{
@ -123,8 +129,8 @@ TEST_CASE_BEGIN(DefaultValues)
T to;
Reader reader(output_buffer.GetBuffer());
bond::Deserialize(reader, to);
UT_AssertIsTrue(obj == to);
bond::Deserialize<Protocols>(reader, to);
UT_Compare_P(obj, to, Protocols);
}
TEST_CASE_END
@ -144,23 +150,23 @@ TEST_CASE_BEGIN(SerializeAPIs)
{
T to;
Deserialize(reader, to);
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
T to;
Deserialize(reader, to, bond::GetRuntimeSchema<T>());
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
auto to = bond::Deserialize<T>(reader);
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
auto to = bond::Deserialize<T>(reader, bond::GetRuntimeSchema<T>());
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
}
@ -182,35 +188,35 @@ TEST_CASE_BEGIN(MarshalAPIs)
{
T to;
Unmarshal(input, to);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
bond::bonded<T> to;
Unmarshal(input, to);
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
T to;
Unmarshal(input, to, bond::GetRuntimeSchema<T>());
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
bond::bonded<T> to;
Unmarshal(input, to, bond::GetRuntimeSchema<T>());
UT_AssertIsTrue(Equal(from, to));
UT_Equal(from, to);
}
{
auto to = bond::Unmarshal<T>(input);
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
{
auto to = bond::Unmarshal<T>(input, bond::GetRuntimeSchema<T>());
UT_AssertIsTrue(from == to);
UT_Compare(from, to);
}
}
TEST_CASE_END
@ -234,10 +240,10 @@ void SimpleStructTests(const char* name)
AllBindingAndMapping1, Reader, Writer, UsingImport>(suite, "Imported struct");
AddTestCase<TEST_ID(N),
DefaultValues, Reader, Writer, StructWithDefaults>(suite, "Omitting default values");
DefaultValues, Reader, Writer, StructWithDefaults, bond::BuiltInProtocols>(suite, "Omitting default values");
AddTestCase<TEST_ID(N),
DefaultValues, Reader, Writer, OptionalContainers>(suite, "Omitting empty containers");
DefaultValues, Reader, Writer, OptionalContainers, bond::BuiltInProtocols>(suite, "Omitting empty containers");
AddTestCase<TEST_ID(N),
AllBindingAndMapping2, Reader, Writer, NestedStruct1, NestedStruct1OptionalBondedView>(suite, "Optional bonded field");
@ -259,19 +265,19 @@ void SimpleStructTests(const char* name)
}
template <uint16_t N, typename Reader, typename Writer>
template <uint16_t N, typename Reader, typename Writer, typename Protocols>
void OmittingDefaultsTests(const char* name)
{
UnitTestSuite suite(name);
AddTestCase<TEST_ID(N),
DefaultValues, Reader, Writer, StructWithDefaults>(suite, "Omitting default values");
DefaultValues, Reader, Writer, StructWithDefaults, Protocols>(suite, "Omitting default values");
AddTestCase<TEST_ID(N),
DefaultValues, Reader, Writer, OptionalContainers>(suite, "Omitting empty containers");
DefaultValues, Reader, Writer, OptionalContainers, Protocols>(suite, "Omitting empty containers");
AddTestCase<TEST_ID(N),
DefaultValues, Reader, Writer, OptionalNothing>(suite, "Omitting nothing");
DefaultValues, Reader, Writer, OptionalNothing, Protocols>(suite, "Omitting nothing");
}
@ -308,7 +314,8 @@ void SerializationTest::SimpleStructTestsInit()
OmittingDefaultsTests<
0x905,
UntaggedProtocolReader<bond::InputBuffer>,
UntaggedProtocolWriter<bond::OutputBuffer> >("Omitting defaults for untagged protocol");
UntaggedProtocolWriter<bond::OutputBuffer>,
bond::BuiltInProtocols::Append<UntaggedProtocolReader<bond::InputBuffer> > >("Omitting defaults for untagged protocol");
}

Просмотреть файл

@ -1,83 +1,80 @@
#pragma once
namespace unittest
{
inline bool operator==(const SimpleStruct& left, const SimpleStructView& right)
template <typename Protocols>
inline bool Compare(const SimpleStruct& left, const SimpleStructView& right)
{
return left.m_bool == right.m_bool
&& left.m_str == right.m_str
&& left.m_int8 == right.m_int8
&& left.m_uint64 == right.m_uint64
&& left.m_float == right.m_float
&& left.m_enum1 == right.m_enum1;
return Compare<Protocols>(left.m_bool, right.m_bool)
&& Compare<Protocols>(left.m_str, right.m_str)
&& Compare<Protocols>(left.m_int8, right.m_int8)
&& Compare<Protocols>(left.m_uint64, right.m_uint64)
&& Compare<Protocols>(left.m_float, right.m_float)
&& Compare<Protocols>(left.m_enum1, right.m_enum1);
}
inline bool operator==(const NestedStruct& left, const NestedStructView& right)
template <typename Protocols>
inline bool Compare(const NestedStruct& left, const NestedStructView& right)
{
return left.m_int8 == right.m_int8
&& left.m_int16 == right.m_int16
&& Equal(left.n1, right.n1);
return Compare<Protocols>(left.m_int8, right.m_int8)
&& Compare<Protocols>(left.m_int16, right.m_int16)
&& Equal<Protocols>(left.n1, right.n1);
}
inline bool operator==(const StructWithBase& left, const SimpleStruct& right)
template <typename Protocols>
inline bool Compare(const StructWithBase& left, const SimpleStruct& right)
{
return Equal(static_cast<SimpleStruct>(left), right);
return Equal<Protocols>(static_cast<SimpleStruct>(left), right);
}
inline bool operator==(const StructWithBase& left, const SimpleBase& right)
template <typename Protocols>
inline bool Compare(const StructWithBase& left, const SimpleBase& right)
{
return Equal(static_cast<SimpleBase>(left), right);
return Equal<Protocols>(static_cast<SimpleBase>(left), right);
}
inline bool operator==(const SimpleBase& left, const SimpleBaseView& right)
template <typename Protocols>
inline bool Compare(const SimpleBase& left, const SimpleBaseView& right)
{
return left.m_int32 == right.m_int32
&& left.m_enum1 == right.m_enum1
&& BaseIsEqual(left, right);
return Compare<Protocols>(left.m_int32, right.m_int32)
&& Compare<Protocols>(left.m_enum1, right.m_enum1)
&& BaseIsEqual<Protocols>(left, right);
}
inline bool operator==(const StructWithBase& left, const StructWithBaseView& right)
template <typename Protocols>
inline bool Compare(const StructWithBase& left, const StructWithBaseView& right)
{
return left.m_str == right.m_str
&& left.m_uint32 == right.m_uint32
&& BaseIsEqual(left, right);
return Compare<Protocols>(left.m_str, right.m_str)
&& Compare<Protocols>(left.m_uint32, right.m_uint32)
&& BaseIsEqual<Protocols>(left, right);
}
inline bool operator==(const NestedWithBase& left, const NestedWithBaseView& right)
template <typename Protocols>
inline bool Compare(const NestedWithBase& left, const NestedWithBaseView& right)
{
return Equal(left.n2, right.n2)
&& Equal(left.d, right.d)
&& BaseIsEqual(left, right);
return Equal<Protocols>(left.n2, right.n2)
&& Equal<Protocols>(left.d, right.d)
&& BaseIsEqual<Protocols>(left, right);
}
inline bool operator==(const NestedWithBase& left, const NestedWithBase2& right)
template <typename Protocols>
inline bool Compare(const NestedWithBase& left, const NestedWithBase2& right)
{
return Equal(static_cast<NestedWithBase2>(left), right);
return Equal<Protocols>(static_cast<NestedWithBase2>(left), right);
}
inline bool operator==(const ListWithBase& left, const ListWithBaseView& right)
template <typename Protocols>
inline bool Compare(const ListWithBase& left, const ListWithBaseView& right)
{
return Equal(left.l1, right.l1)
&& Equal(left.v3, right.v3);
return Equal<Protocols>(left.l1, right.l1)
&& Equal<Protocols>(left.v3, right.v3);
}
template <typename NestedStruct1>
inline bool operator==(const NestedStruct1& left, const NestedStruct1OptionalBondedView& right)
template <typename Protocols, typename NestedStruct1>
inline bool Compare(const NestedStruct1& left, const NestedStruct1OptionalBondedView& right)
{
return Equal(left.s, right.s);
return Equal<Protocols>(left.s, right.s);
}
} // namespace unittest
class SerializationTest
{

Просмотреть файл

@ -113,171 +113,34 @@ private:
};
// Unspecialized unit test wrappers
template <bool Enable, typename Test>
struct TestCase
template <uint32_t Key, typename Test>
inline void AddTestCase(UnitTestSuite& suite, const char* name, std::true_type)
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test::Run, key, name);
}
};
suite.Add(Test::Run, Key, name);
}
template <bool Enable, template <typename T1> class Test, typename T1>
struct TestCase1
template <uint32_t Key, typename Test>
inline void AddTestCase(UnitTestSuite& /*suite*/, const char* /*name*/, std::false_type)
{}
template <uint32_t Key, template <typename...> class Test, typename... T>
inline void AddTestCase(UnitTestSuite& suite, const char* name, std::true_type)
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1>::Run, key, name);
}
};
suite.Add(Test<T...>::Run, Key, name);
}
template <bool Enable, template <typename T1, typename T2> class Test, typename T1, typename T2>
struct TestCase2
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1, T2>::Run, key, name);
}
};
template <uint32_t Key, template <typename...> class Test, typename... T>
inline void AddTestCase(UnitTestSuite& /*suite*/, const char* /*name*/, std::false_type)
{}
template <bool Enable, template <typename T1, typename T2, typename T3> class Test, typename T1, typename T2, typename T3>
struct TestCase3
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1, T2, T3>::Run, key, name);
}
};
template <bool Enable, template <typename T1, typename T2, typename T3, typename T4> class Test, typename T1, typename T2, typename T3, typename T4>
struct TestCase4
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1, T2, T3, T4>::Run, key, name);
}
};
template <bool Enable, template <typename T1, typename T2, typename T3, typename T4, typename T5> class Test, typename T1, typename T2, typename T3, typename T4, typename T5>
struct TestCase5
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1, T2, T3, T4, T5>::Run, key, name);
}
};
template <bool Enable, template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> class Test, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct TestCase6
{
static void Register(UnitTestSuite& suite, uint32_t key, const char* name)
{
suite.Add(Test<T1, T2, T3, T4, T5, T6>::Run, key, name);
}
};
// Unit test wrapper specialization for disabled tests
template <typename Test>
struct TestCase<false, Test>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1> class Test, typename T1>
struct TestCase1<false, Test, T1>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1, typename T2> class Test, typename T1, typename T2>
struct TestCase2<false, Test, T1, T2>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1, typename T2, typename T3> class Test, typename T1, typename T2, typename T3>
struct TestCase3<false, Test, T1, T2, T3>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1, typename T2, typename T3, typename T4> class Test, typename T1, typename T2, typename T3, typename T4>
struct TestCase4<false, Test, T1, T2, T3, T4>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1, typename T2, typename T3, typename T4, typename T5> class Test, typename T1, typename T2, typename T3, typename T4, typename T5>
struct TestCase5<false, Test, T1, T2, T3, T4 ,T5>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
template <template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> class Test, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct TestCase6<false, Test, T1, T2, T3, T4 ,T5, T6>
{
static void Register(UnitTestSuite& /*suite*/, uint32_t /*key*/, const char* /*name*/)
{
}
};
// Helper function to add a unit test
template <bool Pred, uint32_t Key, typename Test>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase<ENABLE(Pred, Key), Test>().Register(suite, Key, name);
AddTestCase<Key, Test>(suite, name, std::integral_constant<bool, ENABLE(Pred, Key)>{});
}
template <bool Pred, uint32_t Key, template <typename T1> class Test, typename T1>
template <bool Pred, uint32_t Key, template <typename...> class Test, typename... T>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase1<ENABLE(Pred, Key), Test, T1>().Register(suite, Key, name);
AddTestCase<Key, Test, T...>(suite, name, std::integral_constant<bool, ENABLE(Pred, Key)>{});
}
template <bool Pred, uint32_t Key, template <typename T1, typename T2> class Test, typename T1, typename T2>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase2<ENABLE(Pred, Key), Test, T1, T2>().Register(suite, Key, name);
}
template <bool Pred, uint32_t Key, template <typename T1, typename T2, typename T3> class Test, typename T1, typename T2, typename T3>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase3<ENABLE(Pred, Key), Test, T1, T2, T3>().Register(suite, Key, name);
}
template <bool Pred, uint32_t Key, template <typename T1, typename T2, typename T3, typename T4> class Test, typename T1, typename T2, typename T3, typename T4>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase4<ENABLE(Pred, Key), Test, T1, T2, T3, T4>().Register(suite, Key, name);
}
template <bool Pred, uint32_t Key, template <typename T1, typename T2, typename T3, typename T4, typename T5> class Test, typename T1, typename T2, typename T3, typename T4, typename T5>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase5<ENABLE(Pred, Key), Test, T1, T2, T3, T4, T5>().Register(suite, Key, name);
}
template <bool Pred, uint32_t Key, template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> class Test, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
inline void AddTestCase(UnitTestSuite& suite, const char* name)
{
TestCase6<ENABLE(Pred, Key), Test, T1, T2, T3, T4, T5, T6>().Register(suite, Key, name);
}

Просмотреть файл

@ -96,6 +96,19 @@ struct SkipTypes
};
template <typename T> struct
is_protocols
: std::false_type {};
template <typename... T> struct
is_protocols<bond::Protocols<T...>>
: std::true_type {};
template <> struct
is_protocols<bond::BuiltInProtocols>
: std::true_type {};
template <typename T>
const std::vector<T>& IntegerConstants()
{
@ -112,6 +125,7 @@ const std::vector<T>& IntegerConstants()
// CreateSelfMappings creates mappings compatible with MapTo<T> transform
// for every field of the specified bond structure.
template <typename Protocols>
class CreateSelfMappings
: public bond::SerializingTransform
{
@ -135,7 +149,7 @@ public:
bool Base(const T& value) const
{
_path.push_back(bond::mapping_base);
bond::Apply(CreateSelfMappings(_mappings[bond::mapping_base].fields, _path), value);
bond::Apply<Protocols>(CreateSelfMappings(_mappings[bond::mapping_base].fields, _path), value);
_path.pop_back();
return false;
}
@ -156,7 +170,7 @@ public:
Field(uint16_t id, const bond::Metadata& /*metadata*/, const T& value) const
{
_path.push_back(id);
bond::Apply(CreateSelfMappings(_mappings[id].fields, _path), value);
bond::Apply<Protocols>(CreateSelfMappings(_mappings[id].fields, _path), value);
_path.pop_back();
return false;
@ -247,45 +261,45 @@ struct Factory<bond::CompactBinaryWriter<Buffer> >
};
template <typename Reader, typename Writer, typename T>
template <typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols, typename T>
Reader Serialize(const T& x, uint16_t version = bond::v1)
{
typename Writer::Buffer output_buffer(4096);
// serialize value to output
Factory<Writer>::Call(output_buffer, version, boost::bind(
bond::Serialize<T, Writer>, x, _1));
bond::Serialize<Protocols, T, Writer>, x, _1));
typename Reader::Buffer input_buffer(output_buffer.GetBuffer());
return Factory<Reader>::Create(input_buffer, version);
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols, typename From, typename To>
typename boost::disable_if<bond::uses_static_parser<Reader> >::type
SerializeDeserialize(const From& from, To& to, uint16_t version = bond::v1)
{
bond::Deserialize(Serialize<Reader, Writer>(from, version), to);
bond::Deserialize<Protocols>(Serialize<Reader, Writer, Protocols>(from, version), to);
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols, typename From, typename To>
typename boost::enable_if<bond::uses_static_parser<Reader> >::type
SerializeDeserialize(const From& from, To& to, uint16_t version = bond::v1)
{
bond::bonded<void>(Serialize<Reader, Writer>(from, version), bond::GetRuntimeSchema<From>()).Deserialize(to);
bond::bonded<void>(Serialize<Reader, Writer, Protocols>(from, version), bond::GetRuntimeSchema<From>()).template Deserialize<Protocols>(to);
}
template <typename Reader, typename Writer, typename Payload, typename T>
template <typename Reader, typename Writer, typename Protocols = bond::BuiltInProtocols, typename Payload, typename T>
Reader Merge(const Payload& payload, const T& x, uint16_t version = bond::v1)
{
typename Writer::Buffer output_buffer;
// merge x with serialized payload into output
Factory<Writer>::Call(output_buffer, version, boost::bind(
bond::Merge<T, Reader, Writer>, x, Serialize<Reader, Writer>(payload, version), _1));
bond::Merge<Protocols, T, Reader, Writer>, x, Serialize<Reader, Writer, Protocols>(payload, version), _1));
typename Reader::Buffer input_buffer(output_buffer.GetBuffer());
@ -293,14 +307,14 @@ Reader Merge(const Payload& payload, const T& x, uint16_t version = bond::v1)
}
template <typename Reader, typename Writer, typename BondedType, typename T>
template <typename Reader, typename Writer, typename BondedType, typename Protocols = bond::BuiltInProtocols, typename T>
bond::bonded<BondedType> GetBonded(T x, uint16_t version = bond::v1)
{
return bond::bonded<BondedType>(Serialize<Reader, Writer>(x, version));
return bond::bonded<BondedType>(Serialize<Reader, Writer, Protocols>(x, version));
}
template <typename T>
template <typename Protocols = bond::BuiltInProtocols, typename T>
void InitRandom(T& x, uint32_t max_string_length = c_max_string_length, uint32_t max_list_size = c_max_list_size)
{
// Instead of deserializing directly from RandomProtocolReader to instance of T
@ -314,11 +328,11 @@ void InitRandom(T& x, uint32_t max_string_length = c_max_string_length, uint32_t
bond::OutputBuffer buffer(1024);
bond::FastBinaryWriter<bond::OutputBuffer> writer(buffer);
random.Serialize(writer);
random.template Serialize<Protocols>(writer);
bond::FastBinaryReader<bond::InputBuffer> reader(buffer.GetBuffer());
bond::Deserialize(reader, x);
bond::Deserialize<Protocols>(reader, x);
}
@ -336,12 +350,12 @@ void Fixup(SkipStruct<T>& x)
}
template <typename T>
template <typename T, typename Protocols = bond::BuiltInProtocols>
T InitRandom(uint32_t max_string_length = c_max_string_length, uint32_t max_list_size = c_max_list_size)
{
T x;
InitRandom(x, max_string_length, max_list_size);
InitRandom<Protocols>(x, max_string_length, max_list_size);
return x;
}
@ -352,21 +366,21 @@ is_optional_field
: std::is_same<typename Field::field_modifier, bond::reflection::optional_field_modifier> {};
template <typename T>
template <typename Protocols = bond::BuiltInProtocols, typename T>
void CopyAndMove(const T& src)
{
T x(src);
UT_AssertIsTrue(Equal(x, src));
UT_Equal_P(x, src, Protocols);
#ifndef BOND_NO_CXX11_RVALUE_REFERENCES
T y(std::move(x));
UT_AssertIsTrue(Equal(y, src));
UT_Equal_P(y, src, Protocols);
UT_AssertIsTrue(moved(x));
#endif
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
void Binding(const From& from, uint16_t version = bond::v1)
{
BOOST_STATIC_ASSERT((std::is_same<BondedType, From>::value
@ -374,7 +388,7 @@ void Binding(const From& from, uint16_t version = bond::v1)
// Compile-time schema
{
bond::bonded<BondedType> bonded(GetBonded<Reader, Writer, BondedType>(from, version));
bond::bonded<BondedType> bonded(GetBonded<Reader, Writer, BondedType, Protocols>(from, version));
To to;
@ -387,18 +401,18 @@ void Binding(const From& from, uint16_t version = bond::v1)
#pragma warning(pop)
#endif
{
to = InitRandom<To>();
to = InitRandom<To, Protocols>();
Fixup(to);
}
Apply(bond::To<To>(to), bonded);
bond::Apply<Protocols>(bond::To<To, Protocols>(to), bonded);
UT_AssertIsTrue(Equal(from, to));
UT_Equal_P(from, to, Protocols);
}
// Runtime schema
{
bond::bonded<void> bonded(GetBonded<Reader, Writer, BondedType>(from, version));
bond::bonded<void> bonded(GetBonded<Reader, Writer, BondedType, Protocols>(from, version));
To to;
@ -411,41 +425,41 @@ void Binding(const From& from, uint16_t version = bond::v1)
#pragma warning(pop)
#endif
{
to = InitRandom<To>();
to = InitRandom<To, Protocols>();
Fixup(to);
}
Apply(bond::To<To>(to), bonded);
bond::Apply<Protocols>(bond::To<To, Protocols>(to), bonded);
UT_AssertIsTrue(Equal(from, to));
UT_Equal_P(from, to, Protocols);
}
CopyAndMove(from);
CopyAndMove<Protocols>(from);
}
template <typename To, typename BondedType>
template <typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<(bond::detail::hierarchy_depth<typename BondedType::Schema>::value
== bond::detail::hierarchy_depth<typename To::Schema>::value)>::type
InitMappings(bond::Mappings& mappings)
{
To to;
bond::Apply(CreateSelfMappings(mappings), to);
bond::Apply<Protocols>(CreateSelfMappings<Protocols>(mappings), to);
}
template <typename To, typename BondedType>
template <typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<(bond::detail::hierarchy_depth<typename BondedType::Schema>::value
> bond::detail::hierarchy_depth<typename To::Schema>::value)>::type
InitMappings(bond::Mappings& mappings)
{
// The data we are deserializing has deeper hierarchy than the target variable
// so we will only map fields of the base struct, and recurse to next level.
InitMappings<To, typename BondedType::Schema::base>(mappings[bond::mapping_base].fields);
InitMappings<To, typename BondedType::Schema::base, Protocols>(mappings[bond::mapping_base].fields);
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
void Mapping(const From& from, uint16_t version = bond::v1)
{
#ifdef UNIT_TEST_MAPPING
@ -458,36 +472,36 @@ void Mapping(const From& from, uint16_t version = bond::v1)
// Compile-time schema
{
bond::bonded<BondedType> bonded(GetBonded<Reader, Writer, BondedType>(from, version));
bond::bonded<BondedType> bonded(GetBonded<Reader, Writer, BondedType, Protocols>(from, version));
To to;
if (boost::mpl::count_if<From::Schema::fields, is_optional_field<_> >::value == 0)
{
to = InitRandom<To>();
to = InitRandom<To, Protocols>();
Fixup(to);
}
Apply(bond::MapTo<To>(to, mappings), bonded);
bond::Apply<Protocols>(bond::MapTo<To, Protocols>(to, mappings), bonded);
UT_AssertIsTrue(Equal(from, to));
UT_Equal_P(from, to, Protocols);
}
// Runtime schema
{
bond::bonded<void> bonded(GetBonded<Reader, Writer, BondedType>(from, version));
bond::bonded<void> bonded(GetBonded<Reader, Writer, BondedType, Protocols>(from, version));
To to;
if (boost::mpl::count_if<From::Schema::fields, is_optional_field<_> >::value == 0)
{
to = InitRandom<To>();
to = InitRandom<To, Protocols>();
Fixup(to);
}
Apply(bond::MapTo<To>(to, mappings), bonded);
bond::Apply<Protocols>(bond::MapTo<To, Protocols>(to, mappings), bonded);
UT_AssertIsTrue(Equal(from, to));
UT_Equal_P(from, to, Protocols);
}
#else
(void)from;
@ -496,101 +510,102 @@ void Mapping(const From& from, uint16_t version = bond::v1)
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
void AllBinding()
{
// default value
Binding<Reader, Writer, From, To, BondedType>(From());
Binding<Reader, Writer, From, To, BondedType>(From(), Reader::version);
Binding<Reader, Writer, From, To, BondedType, Protocols>(From());
Binding<Reader, Writer, From, To, BondedType, Protocols>(From(), Reader::version);
// random values
for (uint32_t i = 0; i < c_iterations; ++i)
{
Binding<Reader, Writer, From, To, BondedType>(InitRandom<From>());
Binding<Reader, Writer, From, To, BondedType>(InitRandom<From>(), Reader::version);
Binding<Reader, Writer, From, To, BondedType, Protocols>(InitRandom<From, Protocols>());
Binding<Reader, Writer, From, To, BondedType, Protocols>(InitRandom<From, Protocols>(), Reader::version);
}
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
void AllMapping()
{
// default value
Mapping<Reader, Writer, From, To, BondedType>(From());
Mapping<Reader, Writer, From, To, BondedType>(From(), Reader::version);
Mapping<Reader, Writer, From, To, BondedType, Protocols>(From());
Mapping<Reader, Writer, From, To, BondedType, Protocols>(From(), Reader::version);
// random values
for (uint32_t i = 0; i < c_iterations; ++i)
{
Mapping<Reader, Writer, From, To, BondedType>(InitRandom<From>());
Mapping<Reader, Writer, From, To, BondedType>(InitRandom<From>(), Reader::version);
Mapping<Reader, Writer, From, To, BondedType, Protocols>(InitRandom<From, Protocols>());
Mapping<Reader, Writer, From, To, BondedType, Protocols>(InitRandom<From, Protocols>(), Reader::version);
}
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::disable_if<bond::uses_static_parser<Reader> >::type
BindingAndMapping(const From& from)
{
Binding<Reader, Writer, From, To, From>(from);
Mapping<Reader, Writer, From, To, From>(from);
Binding<Reader, Writer, From, To, From, Protocols>(from);
Mapping<Reader, Writer, From, To, From, Protocols>(from);
// For dynamic parser the schema doesn't have to exactly match the payload
Binding<Reader, Writer, From, To, To>(from);
Mapping<Reader, Writer, From, To, To>(from);
Binding<Reader, Writer, From, To, To, Protocols>(from);
Mapping<Reader, Writer, From, To, To, Protocols>(from);
}
template <typename Reader, typename Writer, typename From, typename To>
template <typename Reader, typename Writer, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if<bond::uses_static_parser<Reader> >::type
BindingAndMapping(const From& from)
{
Binding<Reader, Writer, From, To, From>(from);
Mapping<Reader, Writer, From, To, From>(from);
Binding<Reader, Writer, From, To, From, Protocols>(from);
Mapping<Reader, Writer, From, To, From, Protocols>(from);
}
template <typename Reader, typename Writer, typename T>
void AllBindingAndMapping()
{
AllBinding<Reader, Writer, T, T, T>();
AllMapping<Reader, Writer, T, T, T>();
}
template <typename Reader, typename Writer, typename From, typename To>
typename boost::disable_if<bond::uses_static_parser<Reader> >::type
template <typename Reader, typename Writer, typename T, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<!is_protocols<T>::value && is_protocols<Protocols>::value>::type
AllBindingAndMapping()
{
AllBinding<Reader, Writer, From, To, From>();
AllMapping<Reader, Writer, From, To, From>();
AllBinding<Reader, Writer, T, T, T, Protocols>();
AllMapping<Reader, Writer, T, T, T, Protocols>();
}
template <typename Reader, typename Writer, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<!bond::uses_static_parser<Reader>::value && !is_protocols<To>::value && is_protocols<Protocols>::value>::type
AllBindingAndMapping()
{
AllBinding<Reader, Writer, From, To, From, Protocols>();
AllMapping<Reader, Writer, From, To, From, Protocols>();
// For dynamic parser the schema doesn't have to exactly match the payload
AllBinding<Reader, Writer, From, To, To>();
AllMapping<Reader, Writer, From, To, To>();
AllBinding<Reader, Writer, From, To, To, Protocols>();
AllMapping<Reader, Writer, From, To, To, Protocols>();
}
template <typename Reader, typename Writer, typename From, typename To>
typename boost::enable_if<bond::uses_static_parser<Reader> >::type
template <typename Reader, typename Writer, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<bond::uses_static_parser<Reader>::value && !is_protocols<To>::value && is_protocols<Protocols>::value>::type
AllBindingAndMapping()
{
AllBinding<Reader, Writer, From, To, From>();
AllMapping<Reader, Writer, From, To, From>();
AllBinding<Reader, Writer, From, To, From, Protocols>();
AllMapping<Reader, Writer, From, To, From, Protocols>();
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
typename boost::disable_if<bond::uses_static_parser<Reader> >::type
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<!bond::uses_static_parser<Reader>::value && !is_protocols<BondedType>::value && is_protocols<Protocols>::value>::type
AllBindingAndMapping()
{
AllBinding<Reader, Writer, From, To, BondedType>();
AllMapping<Reader, Writer, From, To, BondedType>();
AllBinding<Reader, Writer, From, To, BondedType, Protocols>();
AllMapping<Reader, Writer, From, To, BondedType, Protocols>();
}
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
typename boost::enable_if<bond::uses_static_parser<Reader> >::type
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
typename boost::enable_if_c<bond::uses_static_parser<Reader>::value && !is_protocols<BondedType>::value && is_protocols<Protocols>::value>::type
AllBindingAndMapping()
{
// This function is noop for static parser.
@ -601,23 +616,72 @@ AllBindingAndMapping()
// Unit test wrappers for AllBindingAndMapping
#if !defined(_MSC_VER) || _MSC_VER >= 1900
template <typename Reader, typename Writer, typename T, typename Protocols = bond::BuiltInProtocols>
TEST_CASE_BEGIN(AllBindingAndMapping1)
{
AllBindingAndMapping<Reader, Writer, T, Protocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To, typename Protocols = bond::BuiltInProtocols>
TEST_CASE_BEGIN(AllBindingAndMapping2)
{
AllBindingAndMapping<Reader, Writer, From, To, Protocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols = bond::BuiltInProtocols>
TEST_CASE_BEGIN(AllBindingAndMapping3)
{
AllBindingAndMapping<Reader, Writer, From, To, BondedType, Protocols>();
}
TEST_CASE_END
#else
template <typename Reader, typename Writer, typename T>
TEST_CASE_BEGIN(AllBindingAndMapping1)
{
AllBindingAndMapping<Reader, Writer, T>();
AllBindingAndMapping<Reader, Writer, T, bond::BuiltInProtocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename T, typename Protocols>
TEST_CASE_BEGIN(AllBindingAndMapping1_CustomProtocols)
{
AllBindingAndMapping<Reader, Writer, T, Protocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To>
TEST_CASE_BEGIN(AllBindingAndMapping2)
{
AllBindingAndMapping<Reader, Writer, From, To>();
AllBindingAndMapping<Reader, Writer, From, To, bond::BuiltInProtocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To, typename Protocols>
TEST_CASE_BEGIN(AllBindingAndMapping2_CustomProtocols)
{
AllBindingAndMapping<Reader, Writer, From, To, Protocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To, typename BondedType>
TEST_CASE_BEGIN(AllBindingAndMapping3)
{
AllBindingAndMapping<Reader, Writer, From, To, BondedType>();
AllBindingAndMapping<Reader, Writer, From, To, BondedType, bond::BuiltInProtocols>();
}
TEST_CASE_END
template <typename Reader, typename Writer, typename From, typename To, typename BondedType, typename Protocols>
TEST_CASE_BEGIN(AllBindingAndMapping3_CustomProtocols)
{
AllBindingAndMapping<Reader, Writer, From, To, BondedType, Protocols>();
}
TEST_CASE_END
#endif

Просмотреть файл

@ -1,6 +1,7 @@
#pragma once
#include <bond/core/null.h>
#include <bond/core/detail/protocol_visitors.h>
#include <bond/protocol/simple_binary.h>
#include <stack>
@ -12,9 +13,9 @@
template <typename Buffer>
class UntaggedProtocolWriter;
template <typename Buffer>
template <typename Buffer, typename MarshaledBondedProtocols = bond::Protocols<bond::CompactBinaryReader<Buffer> > >
class UntaggedProtocolReader
: public bond::SimpleBinaryReader<Buffer>
: public bond::SimpleBinaryReader<Buffer, MarshaledBondedProtocols>
{
public:
typedef bond::StaticParser<UntaggedProtocolReader&> Parser;
@ -23,7 +24,7 @@ public:
BOND_STATIC_CONSTEXPR uint16_t magic = 0xFFFF;
UntaggedProtocolReader(typename boost::call_traits<Buffer>::param_type input)
: bond::SimpleBinaryReader<Buffer>(input)
: bond::SimpleBinaryReader<Buffer, MarshaledBondedProtocols>(input)
{}
bool ReadVersion()
@ -37,13 +38,12 @@ public:
&& this->_version <= UntaggedProtocolReader::version;
}
using bond::SimpleBinaryReader<Buffer>::Skip;
using bond::SimpleBinaryReader<Buffer, MarshaledBondedProtocols>::Skip;
template <typename T>
void Skip(const bond::bonded<T, UntaggedProtocolReader&>& bonded)
{
// Skip the structure field-by-field by applying Null transform
Apply(bond::Null(), bonded);
bond::detail::Skip(bonded);
}
// ReadStructBegin

Просмотреть файл

@ -5,9 +5,6 @@
#include <bond/core/blob.h>
#include <bond/core/exception.h>
#include <bond/stream/input_buffer.h>
#include <boost/mpl/list.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/mpl/joint_view.hpp>
#include <vector>
#include <fstream>
#include <string>
@ -54,7 +51,15 @@ public:
}
}
InputFile& operator=(const InputFile&);
#if defined(_MSC_VER) && _MSC_VER < 1900
InputFile& operator=(const InputFile& that)
{
InputFile temp(that);
file = std::move(temp.file);
name = std::move(temp.name);
return *this;
}
#endif
bool operator==(const InputFile& that) const
{
@ -90,17 +95,17 @@ public:
return std::make_pair(input, input.file.tellg());
}
friend bond::InputBuffer CreateInputBuffer(const InputFile& /*other*/, const bond::blob& blob)
{
return bond::InputBuffer(blob);
}
private:
mutable std::ifstream file;
std::string name;
};
inline bond::InputBuffer CreateInputBuffer(const InputFile& /*other*/, const bond::blob& blob)
{
return bond::InputBuffer(blob);
}
inline bond::blob GetBufferRange(
std::pair<InputFile, std::ifstream::pos_type> begin,
const std::pair<InputFile, std::ifstream::pos_type>& end)
@ -113,45 +118,8 @@ inline bond::blob GetBufferRange(
}
template <typename InputBuffer>
struct rebind_input_buffer
{
template <typename T> struct
transform
{
typedef T type;
};
template <template <typename> class Reader, typename Buffer> struct
transform<Reader<Buffer>>
{
typedef Reader<InputBuffer> type;
};
};
namespace bond
{
template <> struct
customize<protocols>
{
template <typename T> struct
modify
{
typedef typename boost::mpl::transform_view<
T,
typename rebind_input_buffer<InputFile>::template transform<boost::mpl::_>
>::type protocols_with_inputfile;
BOND_DEFINE_BUFFER_MAGIC(InputFile, 0x4649 /*IF*/);
typedef typename boost::mpl::transform_view<
T,
typename rebind_input_buffer<InputFile&>::template transform<boost::mpl::_>
>::type protocols_with_inputfile_ref;
typedef typename boost::mpl::joint_view<T, protocols_with_inputfile>::type type1;
typedef typename boost::mpl::joint_view<type1, protocols_with_inputfile_ref>::type type;
};
};
} // namespace bond
} // namespace bond

Просмотреть файл

@ -97,6 +97,21 @@ bool TryProtocol(Reader reader, int confidence = 5)
}
// Here using a bond::InputBuffer for marshaled bonded protocols
// instead of defaulted one because corresponding CreateInputBuffer
// returns bond::InputBuffer instead of InputFile.
using MarshaledBondedProtocols = bond::Protocols<bond::CompactBinaryReader<bond::InputBuffer> >;
using NewProtocols = bond::BuiltInProtocols::Append<
bond::CompactBinaryReader<InputFile>,
bond::FastBinaryReader<InputFile>,
bond::SimpleBinaryReader<InputFile, MarshaledBondedProtocols>,
bond::SimpleJsonReader<InputFile>,
bond::CompactBinaryReader<InputFile&>,
bond::FastBinaryReader<InputFile&>,
bond::SimpleBinaryReader<InputFile&, MarshaledBondedProtocols>,
bond::SimpleJsonReader<InputFile&> >;
Protocol Guess(InputFile input)
{
uint16_t word;
@ -134,8 +149,8 @@ bond::SchemaDef LoadSchema(const std::string& file)
tryJson.Read(c);
return (c == '{')
? bond::Deserialize<bond::SchemaDef>(bond::SimpleJsonReader<InputFile>(input))
: bond::Unmarshal<bond::SchemaDef>(input);
? bond::Deserialize<bond::SchemaDef, NewProtocols>(bond::SimpleJsonReader<InputFile>(input))
: bond::Unmarshal<bond::SchemaDef, NewProtocols>(input);
}
template <typename Reader, typename Writer>
@ -144,11 +159,11 @@ void TranscodeFromTo(Reader& reader, Writer& writer, const Options& options)
if (!options.schema.empty() && !options.schema.front().empty())
{
bond::SchemaDef schema(LoadSchema(options.schema.front()));
bond::bonded<void, bond::ProtocolReader>(reader, bond::RuntimeSchema(schema)).Serialize(writer);
bond::bonded<void, bond::ProtocolReader>(reader, bond::RuntimeSchema(schema)).template Serialize<NewProtocols>(writer);
}
else
{
bond::bonded<UnknownSchema, bond::ProtocolReader>(reader).Serialize(writer);
bond::bonded<UnknownSchema, bond::ProtocolReader>(reader).template Serialize<NewProtocols>(writer);
}
}
@ -159,11 +174,11 @@ void TranscodeFromTo(InputFile& input, Writer& writer, const Options& options)
if (!options.schema.empty() && !options.schema.front().empty())
{
bond::SchemaDef schema(LoadSchema(options.schema.front()));
bond::SelectProtocolAndApply(bond::RuntimeSchema(schema), input, SerializeTo(writer));
bond::SelectProtocolAndApply<NewProtocols>(bond::RuntimeSchema(schema), input, bond::SerializeTo<NewProtocols>(writer));
}
else
{
bond::SelectProtocolAndApply<UnknownSchema>(input, SerializeTo(writer));
bond::SelectProtocolAndApply<UnknownSchema, NewProtocols>(input, bond::SerializeTo<NewProtocols>(writer));
}
}

Просмотреть файл

@ -61,7 +61,7 @@ private:
.def(boost::python::init<const T&>())
.def(schema_base_visitor<T>())
.def("Deserialize",
static_cast<void (bonded<T>::*)(T&) const>(&bonded<T>::template Deserialize<T>));
static_cast<void (bonded<T>::*)(T&) const>(&bonded<T>::template Deserialize<BuiltInProtocols, T>));
// Expose struct T to Python
struct_<T>()

Просмотреть файл

@ -367,12 +367,7 @@ private:
InputBuffer input(data);
// A workaround for GCC 4.8 which doesn't resolve the Apply overload below properly.
// Apply<U>(To<U>(obj), input, protocol);
bond::detail::NextProtocol<U>(
typename FilteredProtocols<InputBuffer>::begin(),
typename FilteredProtocols<InputBuffer>::end(),
input,
To<U>(obj),
protocol);
bond::detail::NextProtocol<U, bond::BuiltInProtocols>(input, To<U>(obj), protocol);
}
static void deserialize_schema(const bond::blob& data, U& obj, const bond::SchemaDef& schema, uint16_t protocol = COMPACT_PROTOCOL)