6#include <bond/core/config.h>
8#include "detail/inheritance.h"
9#include "detail/omit_default.h"
10#include "detail/parser_utils.h"
11#include "detail/recursionguard.h"
12#include "detail/typeid_value.h"
14#include "reflection.h"
16#include "transforms.h"
19#include <bond/protocol/simple_binary_impl.h>
20#include <bond/protocol/simple_json_reader_impl.h>
31 template <
typename Transform>
33 ReadFields(
const boost::mpl::l_iter<boost::mpl::l_end>&,
const Transform&)
38 template <
typename Fields>
39 void SkipFields(
const Fields&)
44 template <
typename Transform>
45 struct UnknownFieldBinder
46 : detail::nonassignable
48 UnknownFieldBinder(Transform& transform)
49 : transform(transform)
53 bool Field(uint16_t
id,
const Metadata& ,
const T& value)
const
55 return transform.UnknownField(
id, value);
61 template <
typename Transform>
62 UnknownFieldBinder<Transform> BindUnknownField(Transform& transform)
64 return UnknownFieldBinder<Transform>(transform);
77template <
typename Input>
79 :
protected detail::ParserInheritance<Input, StaticParser<Input> >,
80 public detail::ParserCommon
83 StaticParser(Input input,
bool base =
false)
84 : detail::ParserInheritance<Input, StaticParser<Input> >(input, base)
88 template <
typename Schema,
typename Transform>
90 Apply(
const Transform& transform,
const Schema& schema)
92 detail::StructBegin(_input, _base);
93 bool result = this->Read(schema, transform);
94 detail::StructEnd(_input, _base);
98 friend class detail::ParserInheritance<Input, StaticParser<Input> >;
102 using detail::ParserInheritance<Input, StaticParser<Input> >::_input;
103 using detail::ParserInheritance<Input, StaticParser<Input> >::_base;
104 using detail::ParserCommon::ReadFields;
107 template <
typename Fields>
108 void SkipFields(
const Fields& fields)
111 ReadFields(fields, Null());
115 template <
typename Fields,
typename Transform,
typename I = Input,
116 typename boost::enable_if<detail::implements_field_omitting<I> >::type* =
nullptr>
118 ReadFields(
const Fields&,
const Transform& transform)
120 typedef typename boost::mpl::deref<Fields>::type Head;
122 if (detail::ReadFieldOmitted(_input))
123 detail::OmittedField(Head(), transform);
125 if (
bool done = detail::NonBasicTypeField(Head(), transform, _input))
128 return ReadFields(
typename boost::mpl::next<Fields>::type(), transform);
131 template <
typename Fields,
typename Transform,
typename I = Input,
132 typename boost::disable_if<detail::implements_field_omitting<I> >::type* =
nullptr>
134 ReadFields(
const Fields&,
const Transform& transform)
136 typedef typename boost::mpl::deref<Fields>::type Head;
138 if (
bool done = detail::NonBasicTypeField(Head(), transform, _input))
141 return ReadFields(
typename boost::mpl::next<Fields>::type(), transform);
146 template <
typename Transform>
148 ReadFields(
const RuntimeSchema& schema,
const Transform& transform)
152 for (const_enumerator<std::vector<FieldDef> > enumerator(schema.GetStruct().fields); enumerator.more() && !done;)
154 const FieldDef& field = enumerator.next();
155 const auto type = field.type.id;
157 if (detail::ReadFieldOmitted(_input))
159 transform.OmittedField(field.id, field.metadata, type);
163 if (type == bond::BT_STRUCT || type == bond::BT_LIST || type == bond::BT_SET || type == bond::BT_MAP)
165 done = detail::NonBasicTypeField(field, schema, transform, _input);
169 done = detail::BasicTypeField(field.id, field.metadata, type, transform, _input);
188template <
typename Input>
190 :
protected detail::ParserInheritance<Input, DynamicParser<Input> >,
191 public detail::ParserCommon
194 DynamicParser(Input input,
bool base)
195 : detail::ParserInheritance<Input, DynamicParser<Input> >(input, base)
199 template <
typename Schema,
typename Transform>
201 Apply(
const Transform& transform,
const Schema& schema)
203 detail::RecursionGuard guard;
205 detail::StructBegin(_input, _base);
206 bool result = this->Read(schema, transform);
207 detail::StructEnd(_input, _base);
211 friend class detail::ParserInheritance<Input, DynamicParser<Input> >;
215 using detail::ParserInheritance<Input, DynamicParser<Input> >::_input;
216 using detail::ParserInheritance<Input, DynamicParser<Input> >::_base;
220 template <
typename Fields,
typename Transform>
222 ReadFields(
const Fields& fields,
const Transform& transform)
227 _input.ReadFieldBegin(type,
id);
229 ReadFields(fields,
id, type, transform);
247 ReadUnknownFields(type,
id, transform);
252 done = (type == bond::BT_STOP);
255 _input.ReadFieldEnd();
262 template <
typename Fields,
typename Transform>
264 ReadFields(
const Fields&, uint16_t&
id, BondDataType& type,
const Transform& transform)
266 typedef typename boost::mpl::deref<Fields>::type Head;
270 const bool moveSchemaField = Head::id <= id;
271 if (Head::id ==
id && get_type_id<typename Head::field_type>::value == type)
274 detail::NonBasicTypeField(Head(), transform, _input);
276 else if (Head::id >=
id && type != bond::BT_STOP && type != bond::BT_STOP_BASE)
279 UnknownFieldOrTypeMismatch<is_basic_type<typename Head::field_type>::value>(
288 detail::OmittedField(Head(), transform);
289 goto NextSchemaField;
292 ReadSubsequentField(type,
id);
296 NextSchemaField:
return ReadFields(
typename boost::mpl::next<Fields>::type(),
id, type, transform);
302 template <
typename Transform>
304 ReadFields(
const boost::mpl::l_iter<boost::mpl::l_end>&, uint16_t&
id, BondDataType& type,
const Transform& transform)
306 for (; type != bond::BT_STOP && type != bond::BT_STOP_BASE; ReadSubsequentField(type,
id))
308 UnknownField(
id, type, transform);
316 template <
bool IsBasicType,
typename Transform>
318 typename boost::enable_if_c<IsBasicType, bool>::type
319 UnknownFieldOrTypeMismatch(uint16_t expected_id,
const Metadata& metadata, uint16_t
id, BondDataType type,
const Transform& transform)
321 if (
id == expected_id &&
322 type != bond::BT_LIST &&
323 type != bond::BT_SET &&
324 type != bond::BT_MAP &&
325 type != bond::BT_STRUCT)
327 return detail::BasicTypeField(expected_id, metadata, type, transform, _input);
331 return UnknownField(
id, type, transform);
335 template <
bool IsBasicType,
typename Transform>
337 typename boost::disable_if_c<IsBasicType, bool>::type
338 UnknownFieldOrTypeMismatch(uint16_t ,
const Metadata& , uint16_t
id, BondDataType type,
const Transform& transform)
340 return UnknownField(
id, type, transform);
345 template <
typename Transform>
347 ReadFields(
const RuntimeSchema& schema, uint16_t&
id, BondDataType& type,
const Transform& transform)
349 const auto& fields = schema.GetStruct().fields;
351 for (
auto it = fields.begin(), end = fields.end(); ; ReadSubsequentField(type,
id))
353 while (it != end && (it->id <
id || type == bond::BT_STOP || type == bond::BT_STOP_BASE))
355 const FieldDef& field = *it++;
356 transform.OmittedField(field.id, field.metadata, field.type.id);
359 if (type == bond::BT_STOP || type == bond::BT_STOP_BASE)
364 if (it != end && it->id ==
id)
366 const FieldDef& field = *it++;
368 if (type == bond::BT_STRUCT || type == bond::BT_LIST || type == bond::BT_SET || type == bond::BT_MAP)
370 if (field.type.id == type)
372 detail::NonBasicTypeField(field, schema, transform, _input);
378 detail::BasicTypeField(
id, field.metadata, type, transform, _input);
383 UnknownField(
id, type, transform);
388 template <
typename Transform>
389 void ReadUnknownFields(BondDataType& type, uint16_t&
id,
const Transform& transform)
391 for (; type != bond::BT_STOP; ReadSubsequentField(type,
id))
393 if (type == bond::BT_STOP_BASE)
394 transform.UnknownEnd();
396 UnknownField(
id, type, transform);
401 template <
typename T,
typename Protocols,
typename Val
idator>
402 bool UnknownField(uint16_t, BondDataType type,
const To<T, Protocols, Validator>&)
409 template <
typename Transform>
410 bool UnknownField(uint16_t
id, BondDataType type,
const Transform& transform)
412 if (type == bond::BT_STRUCT)
416 else if (type == bond::BT_LIST || type == bond::BT_SET || type == bond::BT_MAP)
417 return transform.UnknownField(
id, value<void, Input>(_input, type));
419 return detail::BasicTypeField(
id, schema<Unknown>::type::metadata, type, BindUnknownField(transform), _input);
423 void ReadSubsequentField(BondDataType& type, uint16_t&
id)
425 _input.ReadFieldEnd();
426 _input.ReadFieldBegin(type,
id);
436template <
typename Input>
438 :
protected detail::ParserInheritance<Input, DOMParser<Input> >
440 typedef typename std::remove_reference<Input>::type Reader;
443 DOMParser(Input input,
bool base =
false)
444 : detail::ParserInheritance<Input, DOMParser<Input> >(input, base)
448 template <
typename Schema,
typename Transform>
449 bool Apply(
const Transform& transform,
const Schema& schema)
451 detail::RecursionGuard guard;
453 if (!_base) _input.Parse();
454 return this->Read(schema, transform);
457 friend class detail::ParserInheritance<Input, DOMParser<Input> >;
461 using detail::ParserInheritance<Input, DOMParser<Input> >::_input;
462 using detail::ParserInheritance<Input, DOMParser<Input> >::_base;
465 template <
typename Fields>
466 void SkipFields(
const Fields&)
470 template <
typename Fields,
typename Transform>
471 bool ReadFields(
const Fields&,
const Transform& transform)
473 typedef typename boost::mpl::deref<Fields>::type Head;
475 if (
const typename Reader::Field* field = _input.FindField(
478 get_type_id<typename Head::field_type>::value,
479 std::is_enum<typename Head::field_type>::value))
481 Reader input(_input, *field);
482 detail::NonBasicTypeField(Head(), transform, input);
485 return ReadFields(
typename boost::mpl::next<Fields>::type(), transform);
488 template <
typename Transform>
489 bool ReadFields(
const boost::mpl::l_iter<boost::mpl::l_end>&,
const Transform&)
496 template <
typename Transform>
497 bool ReadFields(
const RuntimeSchema& schema,
const Transform& transform)
501 for (const_enumerator<std::vector<FieldDef> > enumerator(schema.GetStruct().fields); enumerator.more() && !done;)
503 const FieldDef& fieldDef = enumerator.next();
504 const auto type = fieldDef.type.id;
506 if (
const typename Reader::Field* field = _input.FindField(fieldDef.id, fieldDef.metadata, type))
508 Reader input(_input, *field);
510 if (type == bond::BT_STRUCT || type == bond::BT_LIST || type == bond::BT_SET || type == bond::BT_MAP)
512 done = detail::NonBasicTypeField(fieldDef, schema, transform, input);
516 done = detail::BasicTypeField(fieldDef.id, fieldDef.metadata, type, transform, input);
530#if BOND_LIB_TYPE != BOND_LIB_TYPE_HEADER
531#include "detail/parser_extern.h"
534#error BOND_LIB_TYPE is undefined
namespace bond
Definition apply.h:17
RuntimeSchema GetRuntimeSchema()
Returns an instance of RuntimeSchema for a user defined struct.
Definition schema.h:336