6#include <bond/core/config.h>
9#include "detail/debug.h"
10#include "detail/double_pass.h"
11#include "detail/marshaled_bonded.h"
12#include "detail/odr.h"
13#include "detail/omit_default.h"
14#include "detail/tags.h"
17#include "reflection.h"
19#include <boost/static_assert.hpp>
32 template <
typename T,
typename Schema,
typename Transform>
45template <
typename Writer,
typename Protocols>
47 :
public SerializingTransform
50 typedef Writer writer_type;
52 BOOST_STATIC_ASSERT(is_writer<Writer>::value);
54 Serializer(Writer& output,
bool base =
false)
60 bool NeedPass0()
const
62 return _output.NeedPass0();
65 template <
typename Pass0>
66 Serializer<Pass0, Protocols> Rebind(Pass0& pass0)
const
68 return Serializer<Pass0, Protocols>(pass0);
71 void Begin(
const Metadata& metadata)
const
73 _output.WriteStructBegin(metadata, _base);
78 _output.WriteStructEnd(_base);
81 void UnknownEnd()
const
83 _output.WriteStructEnd(
true);
87 bool Base(
const T& value)
const
90 Apply<Protocols>(Serializer(_output,
true), value);
95 typename boost::enable_if_c<may_omit_fields<Writer>::value && !is_bond_type<T>::value,
bool>::type
96 Field(uint16_t
id,
const Metadata& metadata,
const T& value)
const
98 if (detail::omit_field<Writer>(metadata, value))
100 detail::WriteFieldOmitted(_output, GetTypeId(value),
id, metadata);
104 WriteField(
id, metadata, value);
108 template <
typename T>
109 typename boost::disable_if_c<may_omit_fields<Writer>::value && !is_bond_type<T>::value,
bool>::type
110 Field(uint16_t
id,
const Metadata& metadata,
const T& value)
const
112 BOOST_ASSERT(!detail::omit_field<Writer>(metadata, value));
114 WriteField(
id, metadata, value);
118 template <
typename T,
typename Reader>
119 bool Field(uint16_t
id,
const Metadata& metadata,
const value<T, Reader>& value)
const
121 BOOST_ASSERT(!detail::omit_field<Writer>(metadata, value));
123 WriteField(
id, metadata, value);
127 template <
typename T,
typename W = Writer>
128 typename boost::enable_if<may_omit_fields<W>,
bool>::type
129 Field(uint16_t
id,
const Metadata& metadata,
const maybe<T>& value)
const
131 if (detail::omit_field<Writer>(metadata, value))
133 detail::WriteFieldOmitted(_output, get_type_id<T>::value,
id, metadata);
137 WriteField(
id, metadata, value.value());
141 template <
typename T,
typename W = Writer>
142 typename boost::disable_if<may_omit_fields<W>,
bool>::type
143 Field(uint16_t
id,
const Metadata& metadata,
const maybe<T>& value)
const
145 BOOST_ASSERT(!detail::omit_field<Writer>(metadata, value));
147 WriteField(
id, metadata, value.value());
152 template <
typename T>
153 bool UnknownField(uint16_t
id,
const T& value)
const
155 _output.WriteFieldBegin(GetTypeId(value),
id);
157 _output.WriteFieldEnd();
163 bool OmittedField(uint16_t
id,
const Metadata& metadata, BondDataType type)
const
165 detail::WriteFieldOmitted(_output, type,
id, metadata);
170 template <
typename T>
171 void Container(
const T& element, uint32_t size)
const
173 _output.WriteContainerBegin(size, GetTypeId(element));
178 _output.WriteContainerEnd();
182 template <
typename Key,
typename T>
183 void Container(
const Key& key,
const T& value, uint32_t size)
const
185 _output.WriteContainerBegin(size, std::make_pair(GetTypeId(key), GetTypeId(value)));
193 _output.WriteContainerEnd();
198 template <
typename T>
199 typename boost::enable_if_c<is_basic_type<T>::value && !is_type_alias<T>::value &&
true>::type
200 WriteField(uint16_t
id,
const Metadata& metadata,
const T& value)
const
202 _output.WriteField(
id, metadata, value);
206 template <
typename T>
207 typename boost::disable_if_c<is_basic_type<T>::value && !is_type_alias<T>::value>::type
208 WriteField(uint16_t
id,
const Metadata& metadata,
const T& value)
const
210 _output.WriteFieldBegin(GetTypeId(value),
id, metadata);
212 _output.WriteFieldEnd();
216 template <
typename T>
217 typename boost::enable_if_c<is_basic_type<T>::value && !is_type_alias<T>::value &&
true>::type
218 Write(
const T& value)
const
220 _output.Write(value);
224 template <
typename T>
225 typename boost::enable_if<is_type_alias<T> >::type
226 Write(
const T& value)
const
228 Write(get_aliased_value(value));
232 template <
typename T>
233 typename boost::enable_if<is_bond_type<T> >::type
234 Write(
const T& value)
const
236 Apply<Protocols>(Serializer(_output), value);
240 template <
typename T>
241 typename boost::enable_if<uses_marshaled_bonded<typename Writer::Reader, T> >::type
242 Write(
const bonded<T>& value)
const
244 detail::MarshalToBlob<Protocols>(value, _output);
248 template <
typename Reader>
249 typename boost::enable_if<uses_marshaled_bonded<typename Writer::Reader, Reader> >::type
250 Write(
const bonded<void, Reader>& value)
const
252 value.template Serialize<Protocols>(_output);
256 template <
typename T1,
typename T2>
257 void Write(
const std::pair<T1, T2>& value)
const
264 template <
typename T>
265 typename boost::enable_if<is_container<T> >::type
266 Write(
const T& value)
const
268 _output.WriteContainerBegin(container_size(value), get_type_id<
typename element_type<T>::type>::value);
270 for (const_enumerator<T> items(value); items.more();)
275 _output.WriteContainerEnd();
280 void Write(
const blob& value)
const
282 _output.WriteContainerBegin(value.length(), get_type_id<blob::value_type>::value);
283 _output.Write(value);
284 _output.WriteContainerEnd();
289 template <
typename Reader,
typename T>
290 typename boost::enable_if<is_basic_type<T> >::type
291 Write(
const value<T, Reader>& value)
const
295 value.template Deserialize<Protocols>(data);
299 template <
typename Reader,
typename T>
300 typename boost::disable_if<is_basic_type<T> >::type
301 Write(
const value<T, Reader>& value)
const
303 Apply<Protocols>(Serializer(_output), value);
307 template <
typename T,
typename WriterT,
typename ProtocolsT>
310 template <
typename T,
typename Reader,
typename Enable>
313 template <
typename T,
typename Schema,
typename Transform>
314 friend class detail::_Parser;
316 template <
typename ProtocolsT,
typename Transform,
typename T>
317 friend bool detail::DoublePassApply(
const Transform&,
const T&);
326template <
typename Protocols,
typename Writer>
327Serializer<Writer, Protocols> SerializeTo(Writer& output)
329 return Serializer<Writer, Protocols>(output);
333template <
typename Writer,
typename Protocols>
335 :
protected Serializer<Writer, Protocols>
338 typedef Writer writer_type;
340 Marshaler(Writer& output)
341 : Serializer<Writer, Protocols>(output)
344 template <
typename T>
345 bool Marshal(
const T& value)
const
347 this->_output.WriteVersion();
348 return Apply<Protocols>(
static_cast<const Serializer<Writer, Protocols>&
>(*
this), value);
356template <
typename Protocols,
typename Writer,
typename T,
typename Reader>
358ApplyTransform(
const Marshaler<Writer, Protocols>& marshaler,
const bonded<T, Reader>& bonded)
360 return marshaler.Marshal(bonded);
364template <
typename Protocols,
typename Writer,
typename T>
366ApplyTransform(
const Marshaler<Writer, Protocols>& marshaler,
const T& value)
368 return marshaler.Marshal(value);
375template <
typename Protocols,
typename Writer>
376Marshaler<Writer, Protocols> MarshalTo(Writer& output)
378 return Marshaler<Writer, Protocols>(output);
383class RequiredFieldValiadator
388 _required = next_required_field<typename schema<T>::type::fields>::value;
391 template <
typename Head>
392 typename boost::enable_if<std::is_same<
typename Head::field_modifier,
393 reflection::required_field_modifier> >::type
396 if (_required == Head::id)
397 _required = next_required_field<typename schema<T>::type::fields, Head::id + 1>::value;
399 MissingFieldException();
403 template <
typename Schema>
404 typename boost::enable_if_c<next_required_field<typename Schema::fields>::value
405 != invalid_field_id>::type
408 if (_required != invalid_field_id)
409 MissingFieldException();
413 template <
typename Head>
414 typename boost::disable_if<std::is_same<
typename Head::field_modifier,
415 reflection::required_field_modifier> >::type
420 template <
typename Schema>
421 typename boost::disable_if_c<next_required_field<typename Schema::fields>::value
422 != invalid_field_id>::type
427 [[noreturn]]
void MissingFieldException()
const;
429 mutable uint16_t _required;
433void RequiredFieldValiadator<T>::MissingFieldException()
const
436 (void)
typename schema<T>::type();
438 BOND_THROW(CoreException,
439 "De-serialization failed: required field " << _required <<
440 " is missing from " << schema<T>::type::metadata.qualified_name);
451 :
public DeserializingTransform
454 void UnknownEnd()
const
457 template <
typename X>
458 bool UnknownField(uint16_t ,
const X& )
const
464 template <
typename Protocols,
typename V,
typename X>
465 void AssignToVar(V& var,
const X& value)
const
467 value.template Deserialize<Protocols>(var);
470 template <
typename Protocols,
typename V,
typename X>
471 void AssignToVar(maybe<V>& var,
const X& value)
const
473 AssignToVar<Protocols>(var.set_value(), value);
476 template <
typename X>
477 bool AssignToField(
const boost::mpl::l_iter<boost::mpl::l_end>&, uint16_t ,
const X& )
const
486template <
typename T,
typename Protocols,
typename Val
idator>
496 void Begin(
const Metadata& )
const
501 BOOST_STATIC_ASSERT(has_schema<T>::value);
503#ifndef BOND_UNIT_TEST_ONLY_PERMIT_OBJECT_REUSE
508 BOOST_ASSERT(detail::OptionalDefault<T>(_var));
516 Validator::template Validate<typename schema<T>::type>();
519 template <
typename X>
520 bool Base(
const X& value)
const
522 return AssignToBase(value);
529 template <
typename Reader,
typename X>
530 bool Field(uint16_t
id,
const Metadata& ,
const bonded<X, Reader>& value)
const
532 return AssignToField(
typename boost::mpl::begin<
typename nested_fields<T>::type>::type(),
id, value);
536 template <
typename Reader,
typename X>
537 bool Field(uint16_t
id,
const Metadata& ,
const value<X, Reader>& value)
const
539 return AssignToField(
typename boost::mpl::begin<
typename matching_fields<T, X>::type>::type(),
id, value);
543 template <
typename Reader>
544 bool Field(uint16_t
id,
const Metadata& ,
const value<void, Reader>& value)
const
546 return AssignToField(
typename boost::mpl::begin<
typename container_fields<T>::type>::type(),
id, value);
552 typedef T FastPathType;
554 template <
typename FieldT,
typename X>
555 bool Field(
const FieldT&,
const X& value)
const
557 Validator::template Validate<FieldT>();
558 AssignToVar<Protocols>(FieldT::GetVariable(_var), value);
563 using detail::To::AssignToVar;
564 using detail::To::AssignToField;
566 template <
typename X,
typename U = T>
567 typename boost::enable_if<has_base<U>,
bool>::type
568 AssignToBase(
const X& value)
const
570 bool done = Apply<Protocols>(To<
typename schema<T>::type::base, Protocols>(_var), value);
574 UnexpectedStructStopException();
580 template <
typename X,
typename U = T>
581 typename boost::disable_if<has_base<U>,
bool>::type
582 AssignToBase(
const X& )
const
587 template <
typename Fields,
typename X>
588 bool AssignToField(
const Fields&, uint16_t
id,
const X& value)
const
590 typedef typename boost::mpl::deref<Fields>::type Head;
594 return Field(Head(), value);
598 return AssignToField(
typename boost::mpl::next<Fields>::type(),
id, value);
602 [[noreturn]]
void UnexpectedStructStopException()
const
605 (void)
typename schema<T>::type();
607 BOND_THROW(CoreException,
608 "De-serialization failed: unexpected struct stop encountered for "
609 << schema<T>::type::metadata.qualified_name);
618typedef std::vector<uint16_t> Path;
619typedef std::map<uint16_t, Mapping> Mappings;
627BOND_STATIC_CONSTEXPR uint16_t mapping_base = invalid_field_id;
638 :
public DeserializingTransform
641 void Begin(
const Metadata& )
const
644 void End(
bool =
false)
const
647 void UnknownEnd()
const
650 template <
typename T>
651 bool UnknownField(uint16_t,
const T&)
const
660 PathView(
const Path& path)
662 current(path.begin())
665 PathView(
const Path& path, Path::const_iterator current)
672 return path.end() - current;
676 const Path::const_iterator current;
680 template <
typename Protocols,
typename V,
typename X>
681 bool Assign(V& var,
const PathView& ids,
const X& value)
const
683 BOOST_ASSERT(ids.size() > 0);
685 if (*ids.current == mapping_base)
686 return AssignToBase<Protocols>(base_class<
typename schema<V>::type>(), var, ids, value);
689 return AssignToField<Protocols>(var, *ids.current, value);
691 return AssignToNested<Protocols>(var, ids, value);
695 template <
typename Protocols,
typename V,
typename X>
696 bool AssignToNested(V& var,
const PathView& ids,
const X& value)
const
698 return AssignToNested<Protocols>(
typename boost::mpl::begin<
typename struct_fields<V>::type>::type(), var, ids, value);
702 template <
typename Protocols,
typename BaseT,
typename V,
typename X>
703 bool AssignToBase(
const BaseT*, V& var,
const PathView& ids,
const X& value)
const
705 return Assign<Protocols>(
static_cast<BaseT&
>(var), PathView(ids.path, ids.current + 1), value);
709 template <
typename Protocols,
typename V,
typename X>
710 bool AssignToBase(
const no_base*, V& ,
const PathView& ,
const X& )
const
716 template <
typename Protocols,
typename Nested,
typename V,
typename X>
717 bool AssignToNested(
const Nested&, V& var,
const PathView& ids,
const X& value)
const
719 typedef typename boost::mpl::deref<Nested>::type Head;
721 if (*ids.current == Head::id)
722 return Assign<Protocols>(Head::GetVariable(var), PathView(ids.path, ids.current + 1), value);
724 return AssignToNested<Protocols>(
typename boost::mpl::next<Nested>::type(), var, ids, value);
727 template <
typename Protocols,
typename V,
typename X>
728 bool AssignToNested(
const boost::mpl::l_iter<boost::mpl::l_end>&, V& ,
const PathView& ,
const X& )
const
737 template <
typename Protocols,
typename Reader,
typename V,
typename X>
738 bool AssignToField(V& var, uint16_t
id,
const bonded<X, Reader>& value)
const
740 return AssignToField<Protocols>(
typename boost::mpl::begin<
typename nested_fields<V>::type>::type(), var,
id, value);
744 template <
typename Protocols,
typename Reader,
typename V,
typename X>
745 bool AssignToField(V& var, uint16_t
id,
const value<X, Reader>& value)
const
747 return AssignToField<Protocols>(
typename boost::mpl::begin<
typename matching_fields<V, X>::type>::type(), var,
id, value);
751 template <
typename Protocols,
typename Reader,
typename V>
752 bool AssignToField(V& var, uint16_t
id,
const value<void, Reader>& value)
const
754 return AssignToField<Protocols>(
typename boost::mpl::begin<
typename container_fields<V>::type>::type(), var,
id, value);
758 template <
typename Protocols,
typename Fields,
typename V,
typename X>
759 bool AssignToField(
const Fields&, V& var, uint16_t
id,
const X& value)
const
761 typedef typename boost::mpl::deref<Fields>::type Head;
765 AssignToVar<Protocols>(Head::GetVariable(var), value);
770 return AssignToField<Protocols>(
typename boost::mpl::next<Fields>::type(), var,
id, value);
775 template <
typename Protocols,
typename V,
typename X>
776 bool AssignToField(
const boost::mpl::l_iter<boost::mpl::l_end>&, V& , uint16_t ,
const X& )
const
782 template <
typename Protocols,
typename V,
typename X>
783 void AssignToVar(V& var,
const X& value)
const
785 value.template Deserialize<Protocols>(var);
789 template <
typename Protocols,
typename V,
typename X>
790 void AssignToVar(maybe<V>& var,
const X& value)
const
792 AssignToVar<Protocols>(var.set_value(), value);
799template <
typename T,
typename Protocols = BuiltInProtocols>
801 :
public detail::MapTo
804 BOOST_STATIC_ASSERT(has_schema<T>::value);
806 MapTo(T& var,
const Mappings& mappings)
812 template <
typename X>
813 bool Base(
const X& value)
const
815 Mappings::const_iterator it = _mappings.find(mapping_base);
817 if (it != _mappings.end())
818 return Apply<Protocols>(MapTo(_var, it->second.fields), value);
823 template <
typename Reader,
typename X>
824 bool Field(uint16_t
id,
const Metadata& ,
const bonded<X, Reader>& value)
const
826 BOOST_ASSERT(
id != mapping_base);
828 Mappings::const_iterator it = _mappings.find(
id);
830 if (it != _mappings.end())
832 if (!it->second.fields.empty())
833 return Apply<Protocols>(MapTo(_var, it->second.fields), value);
835 if (!it->second.path.empty())
836 return Assign<Protocols>(_var, it->second.path, value);
842 template <
typename X>
843 bool Field(uint16_t
id,
const Metadata& ,
const X& value)
const
845 BOOST_ASSERT(
id != mapping_base);
847 Mappings::const_iterator it = _mappings.find(
id);
849 if (it != _mappings.end() && !it->second.path.empty())
850 return Assign<Protocols>(_var, it->second.path, value);
856 using detail::MapTo::Assign;
859 const Mappings& _mappings;
namespace bond
Definition: apply.h:17
bool Validate(const RuntimeSchema &src, const RuntimeSchema &dst)
Validate compatibility of schemas.
Definition: validate.h:24
void Marshal(const T &obj, Writer &output)
Marshal an object using a protocol writer.
Definition: bond.h:63