diff --git a/CHANGELOG.md b/CHANGELOG.md index 9603fd92..3896f1ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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` 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. diff --git a/cpp/inc/bond/comm/message.h b/cpp/inc/bond/comm/message.h index f6b2f734..9c43aca1 100644 --- a/cpp/inc/bond/comm/message.h +++ b/cpp/inc/bond/comm/message.h @@ -8,6 +8,7 @@ #include #include +#include #include namespace bond { namespace comm diff --git a/cpp/inc/bond/comm/transport/packet.h b/cpp/inc/bond/comm/transport/packet.h index 1fb68c04..7a9ae541 100644 --- a/cpp/inc/bond/comm/transport/packet.h +++ b/cpp/inc/bond/comm/transport/packet.h @@ -300,7 +300,7 @@ private: // FIXME - handle Unmarshal errors try { - Unmarshal(buffer, response.error); + Unmarshal(buffer, response.error); } catch (const bond::Exception&) { diff --git a/cpp/inc/bond/core/apply.h b/cpp/inc/bond/core/apply.h index 09202272..ecc29593 100644 --- a/cpp/inc/bond/core/apply.h +++ b/cpp/inc/bond/core/apply.h @@ -16,26 +16,26 @@ namespace detail { /// @brief Apply transform to serialized struct wrapped in bonded -template +template typename boost::disable_if, bool>::type inline ApplyTransform(const Transform& transform, const bonded& bonded) { - return bonded._Apply(transform); + return bonded.template _Apply(transform); } /// @brief Apply transform to serialized container wrapped in value -template +template bool inline ApplyTransform(const Transform& transform, const value& value) { - value._Apply(transform); + value.template _Apply(transform); return true; } /// @brief Apply transform to an instance of a struct -template +template typename boost::disable_if, 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 +template typename boost::enable_if, 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 +template typename boost::enable_if, bool>::type inline ApplyTransform(const Transform& transform, const bonded& bonded) { if (transform.NeedPass0()) - return DoublePassApply(transform, bonded); + return DoublePassApply(transform, bonded); else - return bonded._Apply(transform); + return bonded.template _Apply(transform); } -template +template typename boost::enable_if, bool>::type inline ApplyTransform(const Transform& transform, const T& value) { if (transform.NeedPass0()) - return DoublePassApply(transform, value); + return DoublePassApply(transform, value); else return StaticParser(value).Apply(transform, typename schema::type()); } @@ -77,16 +77,16 @@ ApplyTransform(const Transform& transform, const T& value) } // namespace detail -template >::type* = nullptr> +template >::type*> bool Apply(const Transform& transform, T& value) { - return detail::ApplyTransform(transform, value); + return detail::ApplyTransform(transform, value); } -template +template bool Apply(const Transform& transform, const T& value) { - return detail::ApplyTransform(transform, value); + return detail::ApplyTransform(transform, value); } } // namespace bond diff --git a/cpp/inc/bond/core/bond.h b/cpp/inc/bond/core/bond.h index 566d0600..27cb5613 100644 --- a/cpp/inc/bond/core/bond.h +++ b/cpp/inc/bond/core/bond.h @@ -13,116 +13,116 @@ namespace bond /// @brief Serialize an object using a protocol writer /// -template +template inline void Serialize(const T& obj, Writer& output) { - Apply(Serializer(output), obj); + Apply(Serializer(output), obj); } /// @brief Deserialize an object from a protocol reader -template +template inline void Deserialize(Reader input, T& obj) { - Apply(To(obj), bonded(input)); + Apply(To(obj), bonded(input)); } /// @brief Deserialize an object of type T from a protocol reader -template +template inline T Deserialize(Reader input) { T tmp; - Apply(To(tmp), bonded(input)); + Apply(To(tmp), bonded(input)); return tmp; } /// @brief Deserialize an object from a protocol reader using runtime schema -template +template inline void Deserialize(Reader input, T& obj, const RuntimeSchema& schema) { - Apply(To(obj), bonded(input, schema)); + Apply(To(obj), bonded(input, schema)); } /// @brief Deserialize an object of type T from a protocol reader using runtime schema -template +template inline T Deserialize(Reader input, const RuntimeSchema& schema) { T tmp; - Apply(To(tmp), bonded(input, schema)); + Apply(To(tmp), bonded(input, schema)); return tmp; } /// @brief Marshal an object using a protocol writer -template +template inline void Marshal(const T& obj, Writer& output) { - Apply(Marshaler(output), obj); + Apply(Marshaler(output), obj); } /// @brief Unmarshal an object from data stream -template +template inline void Unmarshal(Buffer input, T& obj) { - SelectProtocolAndApply(input, To(obj)); + SelectProtocolAndApply(input, To(obj)); } /// @brief Unmarshal an object of type T from data stream -template +template inline T Unmarshal(Buffer input) { T tmp; - SelectProtocolAndApply(input, To(tmp)); + SelectProtocolAndApply(input, To(tmp)); return tmp; } /// @brief Initialize a bonded from data stream contained marshaled object -template +template inline void Unmarshal(Buffer input, bonded& obj) { - SelectProtocolAndApply(input, boost::ref(obj)); + SelectProtocolAndApply(input, boost::ref(obj)); } /// @brief Unmarshal an object from data stream using a runtime schema -template +template inline void Unmarshal(Buffer input, T& obj, const RuntimeSchema& schema) { - SelectProtocolAndApply(schema, input, To(obj)); + SelectProtocolAndApply(schema, input, To(obj)); } /// @brief Unmarshal an object of type T from data stream using a runtime schema -template +template inline T Unmarshal(Buffer input, const RuntimeSchema& schema) { T tmp; - SelectProtocolAndApply(schema, input, To(tmp)); + SelectProtocolAndApply(schema, input, To(tmp)); return tmp; } /// @brief Initialize a bonded from data stream contained marshaled object /// using a runtime schema -template +template inline void Unmarshal(Buffer input, bonded& obj, const RuntimeSchema& schema) { - SelectProtocolAndApply(schema, input, boost::ref(obj)); + SelectProtocolAndApply(schema, input, boost::ref(obj)); } /// @brief Merge an object with serialize data and write the result using /// a protocol writer -template +template inline void Merge(const T& obj, Reader input, Writer& output) { - Apply(Merger(obj, output), bonded(input)); + Apply(Merger(obj, output), bonded(input)); } } diff --git a/cpp/inc/bond/core/bond_fwd.h b/cpp/inc/bond/core/bond_fwd.h index dd930021..3244fae0 100644 --- a/cpp/inc/bond/core/bond_fwd.h +++ b/cpp/inc/bond/core/bond_fwd.h @@ -4,8 +4,9 @@ #pragma once #include "config.h" -#include +#include "detail/tags.h" #include +#include namespace bond { @@ -14,7 +15,7 @@ class blob; class InputBuffer; class RuntimeSchema; -struct ProtocolReader; +class ProtocolReader; template class bonded; @@ -43,7 +44,9 @@ class DOMParser; template class RequiredFieldValiadator; -template > +struct BuiltInProtocols; + +template > class To; template struct @@ -62,4 +65,26 @@ struct Metadata; struct qualified_name_tag; -} +template >::type* = nullptr> +bool Apply(const Transform& transform, T& value); + +template +bool Apply(const Transform& transform, const T& value); + +template +inline void Marshal(const T& obj, Writer& output); + +template +class Marshaler; + +template +Marshaler MarshalTo(Writer& output); + +template +class Serializer; + +template +Serializer SerializeTo(Writer& output); + +} // bond + diff --git a/cpp/inc/bond/core/bond_version.h b/cpp/inc/bond/core/bond_version.h index b1be4df5..b0261185 100644 --- a/cpp/inc/bond/core/bond_version.h +++ b/cpp/inc/bond/core/bond_version.h @@ -12,12 +12,15 @@ namespace bond { - template - class SimpleBinaryReader; + template + struct Protocols; template class CompactBinaryReader; + template > > + class SimpleBinaryReader; + BOND_CONSTEXPR_OR_CONST uint16_t v1 = 0x0001; BOND_CONSTEXPR_OR_CONST uint16_t v2 = 0x0002; diff --git a/cpp/inc/bond/core/bonded.h b/cpp/inc/bond/core/bonded.h index 1dfcb2c2..3a054c3d 100644 --- a/cpp/inc/bond/core/bonded.h +++ b/cpp/inc/bond/core/bonded.h @@ -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 +template typename boost::disable_if, bool>::type inline ApplyTransform(const Transform& transform, const bonded& bonded); -template +template typename boost::enable_if, bool>::type inline ApplyTransform(const Transform& transform, const bonded& bonded); @@ -33,7 +35,7 @@ is_marshaled_bonded && is_bonded::value> {}; -template +template inline std::pair SelectProtocolAndApply( Buffer& input, const Transform& transform); @@ -153,46 +155,38 @@ public: } /// @brief Serialize bonded using specified protocol writer - template + template void Serialize(Writer& output) const { - Apply(SerializeTo(output), *this); - } - - /// @brief Deserialize an object of type T - T Deserialize() const - { - T tmp; - Apply(To(tmp), *this); - return tmp; + Apply(SerializeTo(output), *this); } /// @brief Deserialize an object of type X - template + template X Deserialize() const { X tmp; - Apply(To(tmp), *this); + Apply(To(tmp), *this); return tmp; } /// @brief Deserialize to an object of type X - template + template void Deserialize(X& var) const { - Apply(To(var), *this); + Apply(To(var), *this); } /// @brief Deserialize to a bonded - template + template typename boost::enable_if >::type Deserialize(bonded& var) const { - _SelectProtocolAndApply(boost::ref(var)); + _SelectProtocolAndApply(boost::ref(var)); } - template + template typename boost::disable_if >::type Deserialize(bonded& var) const { @@ -201,10 +195,10 @@ public: /// @brief Update bonded payload by merging it with an object of type X - template + template void Merge(const X& var) { - detail::Merge(var, _data); + detail::Merge(var, _data); } @@ -226,11 +220,11 @@ public: } - template + template friend typename boost::disable_if, bool>::type inline detail::ApplyTransform(const Transform& transform, const bonded& bonded); - template + template friend typename boost::enable_if, bool>::type inline detail::ApplyTransform(const Transform& transform, const bonded& bonded); @@ -239,29 +233,29 @@ public: private: // Apply transform to serialized data - template + template typename boost::enable_if, bool>::type _Apply(const Transform& transform) const { - return _SelectProtocolAndApply(transform); + return _SelectProtocolAndApply(transform); } - template + template typename boost::disable_if, bool>::type _Apply(const Transform& transform) const { _skip = false; - return detail::Parse(transform, _data, typename schema_for_passthrough::type(), _schema.get(), _base); + return detail::Parse(transform, _data, typename schema_for_passthrough::type(), _schema.get(), _base); } - template + template bool _SelectProtocolAndApply(const Transform& transform) const { _skip = false; auto input = CreateInputBuffer(_data.GetBuffer(), detail::ReadBlob(_data)); - return SelectProtocolAndApply::type>(input, transform).second; + return SelectProtocolAndApply::type, Protocols>(input, transform).second; } Reader _data; diff --git a/cpp/inc/bond/core/bonded_void.h b/cpp/inc/bond/core/bonded_void.h index 6ce911be..17e51e5d 100644 --- a/cpp/inc/bond/core/bonded_void.h +++ b/cpp/inc/bond/core/bonded_void.h @@ -70,45 +70,45 @@ public: /// @brief Serialize bonded using specified protocol writer - template + template typename boost::disable_if >::type Serialize(Writer& output) const { - Apply(SerializeTo(output), *this); + Apply(SerializeTo(output), *this); } - template + template typename boost::enable_if >::type Serialize(Writer& output) const { if (_schema.GetType().bonded_type) - detail::MarshalToBlob(*this, output); + detail::MarshalToBlob(*this, output); else - Apply(SerializeTo(output), *this); + Apply(SerializeTo(output), *this); } /// @brief Deserialize an object of type T - template + template T Deserialize() const { T tmp; - Apply(To(tmp), *this); + Apply(To(tmp), *this); return tmp; } /// @brief Deserialize to an object of type T - template + template void Deserialize(T& var) const { - Apply(To(var), *this); + Apply(To(var), *this); } /// @brief Deserialize to a bonded - template + template void Deserialize(bonded& var) const { #ifdef _MSC_VER @@ -121,8 +121,8 @@ public: #endif { bonded tmp; - _SelectProtocolAndApply(boost::ref(tmp)); - tmp.Deserialize(var); + _SelectProtocolAndApply(boost::ref(tmp)); + tmp.template Deserialize(var); } else { @@ -139,11 +139,11 @@ public: } - template + template friend typename boost::disable_if, bool>::type inline detail::ApplyTransform(const Transform& transform, const bonded& bonded); - template + template friend typename boost::enable_if, bool>::type inline detail::ApplyTransform(const Transform& transform, const bonded& bonded); @@ -152,7 +152,7 @@ public: private: // Apply transform to serialized data - template + template bool _Apply(const Transform& transform) const { #ifdef _MSC_VER @@ -164,27 +164,27 @@ private: #pragma warning(pop) #endif { - return _SelectProtocolAndApply(transform); + return _SelectProtocolAndApply(transform); } else { _skip = false; - return detail::Parse(transform, _data, _schema, NULL, _base); + return detail::Parse(transform, _data, _schema, NULL, _base); } } - template + template typename boost::enable_if, 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(_schema, input, transform).second; } - template + template typename boost::disable_if, bool>::type _SelectProtocolAndApply(const Transform&) const { diff --git a/cpp/inc/bond/core/customize.h b/cpp/inc/bond/core/customize.h index 34a5429f..0a833567 100644 --- a/cpp/inc/bond/core/customize.h +++ b/cpp/inc/bond/core/customize.h @@ -14,18 +14,4 @@ is_protocol_enabled : false_type {}; -struct protocols; - -// User can modify set of protocols by specializing customize -template struct -customize -{ - template struct - modify - { - typedef T type; - }; -}; - - } diff --git a/cpp/inc/bond/core/detail/any.h b/cpp/inc/bond/core/detail/any.h new file mode 100644 index 00000000..b4d8e1c5 --- /dev/null +++ b/cpp/inc/bond/core/detail/any.h @@ -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 +#include +#include +#include +#include +#include + + +namespace bond +{ +namespace detail +{ + +template