Bond
 
Loading...
Searching...
No Matches
bonded.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "bond_fwd.h"
9#include "detail/double_pass.h"
10#include "detail/marshaled_bonded.h"
11#include "detail/protocol_visitors.h"
12#include "protocol.h"
13#include "runtime_schema.h"
14#include "select_protocol_fwd.h"
15
16namespace bond
17{
18namespace detail
19{
20
21template <typename Protocols, typename Transform, typename T, typename Reader>
22typename boost::disable_if<need_double_pass<Transform>, bool>::type inline
23ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded);
24
25template <typename Protocols, typename Transform, typename T, typename Reader>
26typename boost::enable_if<need_double_pass<Transform>, bool>::type inline
27ApplyTransform(const Transform& transform, const bonded<T, Reader>& bonded);
28
29
30// Helper function move_data for dealing with [not] moving a Reader& in bonded<T, Reader&>
31template <typename T, typename U>
32typename boost::enable_if<std::is_reference<T>, T>::type
33inline move_data(U& data) BOND_NOEXCEPT
34{
35 BOOST_STATIC_ASSERT(std::is_same<T, U&>::value);
36 return data;
37}
38
39template <typename T, typename U>
40typename boost::disable_if<std::is_reference<T>, T&&>::type
41inline move_data(U& data) BOND_NOEXCEPT_IF(
42 std::is_nothrow_move_constructible<T>::value)
43{
44 BOOST_STATIC_ASSERT(std::is_same<T, U>::value);
45 return std::move(data);
46}
47
48} // namespace detail
49
50
51template <typename T, typename Reader, typename Unused = void> struct
52is_marshaled_bonded
53 : std::integral_constant<bool,
54 uses_marshaled_bonded<Reader, Unused>::value
55 && is_bonded<T>::value> {};
56
57
61template <typename T, typename Reader>
62class bonded
63{
64public:
67 : _skip(false),
68 _base(false)
69 {}
70
73 : _data(bonded._data),
74 _schema(bonded._schema),
75 _skip(true),
76 _base(false)
77 {}
78
80 bonded(bonded&& bonded) BOND_NOEXCEPT_IF(
81 BOND_NOEXCEPT_EXPR(detail::move_data<Reader>(bonded._data))
82 && std::is_nothrow_move_constructible<RuntimeSchema>::value)
83 : _data(detail::move_data<Reader>(bonded._data)),
84 _schema(std::move(bonded._schema)),
85 _skip(std::move(bonded._skip)),
86 _base(std::move(bonded._base))
87 {
88 bonded._skip = false;
89 }
90
91 bonded& operator=(const bonded& rhs) = default;
92
94 template <typename U, typename ReaderT>
95 explicit
97 : _data(bonded._data),
98 _schema(bonded._schema),
99 _skip(true),
100 _base(false)
101 {
102 BOOST_STATIC_ASSERT((std::is_base_of<U, T>::value || std::is_base_of<T, U>::value));
103 }
104
105
115 template <typename U>
116 explicit
117 bonded(const U& value)
118 : _data(value),
119 _skip(true),
120 _base(false)
121 {}
122
123
125 explicit
126 bonded(Reader data, bool base = false)
127 : _data(data),
128 _skip(true),
129 _base(base)
130 {}
131
132
134 template <typename ReaderT>
135 explicit
137 : _data(bonded._data),
138 _schema(bonded._schema),
139 _skip(true),
140 _base(false)
141 {}
142
143
144 ~bonded()
145 {
146 // Skip the struct if it wasn't deserialized
147 if (_skip)
148 detail::Skip(_data, *this, std::nothrow);
149 }
150
151
153 template <typename U, typename ReaderT>
154 operator bonded<U, ReaderT>() const
155 {
156 BOOST_STATIC_ASSERT((std::is_base_of<U, T>::value));
157 return bonded<U, ReaderT>(*this);
158 }
159
161 template <typename ReaderT>
162 operator bonded<void, ReaderT>() const
163 {
164 return bonded<void, ReaderT>(*this);
165 }
166
168 template <typename Protocols = BuiltInProtocols, typename Writer>
169 void Serialize(Writer& output) const
170 {
171 Apply<Protocols>(SerializeTo<Protocols>(output), *this);
172 }
173
175 template <typename X = T, typename Protocols = BuiltInProtocols>
176 X Deserialize() const
177 {
178 X tmp;
179 Apply<Protocols>(To<X, Protocols>(tmp), *this);
180 return tmp;
181 }
182
184 template <typename Protocols = BuiltInProtocols, typename X>
185 void Deserialize(X& var) const
186 {
187 Apply<Protocols>(To<X, Protocols>(var), *this);
188 }
189
191 template <typename Protocols = BuiltInProtocols, typename U>
192 typename boost::enable_if<is_marshaled_bonded<T, Reader, U> >::type
193 Deserialize(bonded<U>& var) const
194 {
195 _SelectProtocolAndApply<Protocols>(boost::ref(var));
196 }
197
198
199 template <typename Protocols = BuiltInProtocols, typename U>
200 typename boost::disable_if<is_marshaled_bonded<T, Reader, U> >::type
201 Deserialize(bonded<U>& var) const
202 {
203 var._data = _data;
204 }
205
206
208 template <typename Protocols = BuiltInProtocols, typename X>
209 void Merge(const X& var)
210 {
211 detail::Merge<Protocols>(var, _data);
212 }
213
216 void Skip()
217 {
218 _skip = false;
219 detail::Skip(_data, *this);
220 }
221
222
227 bool operator==(const bonded& rhs) const
228 {
229 return _data == rhs._data;
230 }
231
232
233 template <typename Protocols, typename Transform, typename U, typename ReaderT>
234 friend typename boost::disable_if<detail::need_double_pass<Transform>, bool>::type inline
235 detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
236
237 template <typename Protocols, typename Transform, typename U, typename ReaderT>
238 friend typename boost::enable_if<detail::need_double_pass<Transform>, bool>::type inline
239 detail::ApplyTransform(const Transform& transform, const bonded<U, ReaderT>& bonded);
240
241 template <typename U, typename ReaderT>
242 friend class bonded;
243
244private:
245 // Apply transform to serialized data
246 template <typename Protocols, typename Transform>
247 typename boost::enable_if<is_marshaled_bonded<T, Reader, Transform>, bool>::type
248 _Apply(const Transform& transform) const
249 {
250 return _SelectProtocolAndApply<Protocols>(transform);
251 }
252
253
254 template <typename Protocols, typename Transform>
255 typename boost::disable_if<is_marshaled_bonded<T, Reader, Transform>, bool>::type
256 _Apply(const Transform& transform) const
257 {
258 _skip = false;
259 return detail::Parse<T, Protocols>(transform, _data, typename schema_for_passthrough<T>::type(), _schema.get(), _base);
260 }
261
262
263 template <typename Protocols, typename Transform>
264 bool _SelectProtocolAndApply(const Transform& transform) const
265 {
266 _skip = false;
267 auto input = CreateInputBuffer(_data.GetBuffer(), detail::ReadBlob(_data));
268 return SelectProtocolAndApply<typename remove_bonded<T>::type, Protocols>(input, transform).second;
269 }
270
271 Reader _data;
272 RuntimeSchema _schema;
273 mutable bool _skip;
274 bool _base;
275};
276
277} // namespace bond
Represents data for a struct T known at compile-time.
Definition: bonded.h:63
bonded()
Default constructor.
Definition: bonded.h:66
bool operator==(const bonded &rhs) const
Compare for equality.
Definition: bonded.h:225
void Merge(const X &var)
Update bonded<T> payload by merging it with an object of type X.
Definition: bonded.h:207
bonded(bonded &&bonded) BOND_NOEXCEPT_IF(&&std
Move constructor.
Definition: bonded.h:80
void Serialize(Writer &output) const
Serialize bonded using specified protocol writer.
Definition: bonded.h:167
bonded(const bonded &bonded)
Copy constructor.
Definition: bonded.h:72
X Deserialize() const
Deserialize an object of type X.
Definition: bonded.h:174
void Skip()
Skip struct data in the underlying payload.
Definition: bonded.h:214
namespace bond
Definition: apply.h:17
STL namespace.