6#include <bond/core/config.h>
9#include "detail/metadata.h"
11#include <bond/core/bond_types.h>
13#include <boost/mpl/copy_if.hpp>
14#include <boost/mpl/find_if.hpp>
15#include <boost/mpl/for_each.hpp>
16#include <boost/mpl/list.hpp>
17#include <boost/mpl/push_front.hpp>
18#include <boost/mpl/transform.hpp>
19#include <boost/static_assert.hpp>
28template <
typename T>
struct
35template <
typename T>
struct
36remove_maybe<maybe<T> >
38 typedef typename remove_maybe<T>::type type;
42BOND_STATIC_CONSTEXPR uint16_t invalid_field_id = 0xffff;
51typedef std::map<std::string, std::string> Attributes;
55using required_field_modifier = std::integral_constant<bond::Modifier, bond::Required>;
58using optional_field_modifier = std::integral_constant<bond::Modifier, bond::Optional>;
61using required_optional_field_modifier = std::integral_constant<bond::Modifier, bond::RequiredOptional>;
70 FieldType Struct::*field_ptr,
71 const bond::Metadata* metadata_ptr>
84 typedef typename remove_maybe<FieldType>::type
field_type;
104 BOND_STATIC_CONSTEXPR uint16_t
id = field_id;
110 return object.*field_ptr;
117 return object.*field_ptr;
120 BOOST_STATIC_ASSERT(field_id != invalid_field_id);
126 typename ModifierTag,
129 FieldType Struct::*field_ptr,
130 const Metadata* metadata_ptr>
137 typename ModifierTag,
140 FieldType Struct::*field_ptr,
141 const Metadata* metadata_ptr
149bond::Metadata MetadataInit(
const char* name)
151 bond::Metadata metadata;
153 metadata.name = name;
158bond::Metadata MetadataInit(
const char* name, bond::Modifier modifier,
const Attributes& attributes)
160 bond::Metadata metadata;
162 metadata.name = name;
163 metadata.modifier = modifier;
164 metadata.attributes = attributes;
170bond::Metadata MetadataInit(
const char* name,
const Attributes& attributes)
172 bond::Metadata metadata;
174 metadata.name = name;
175 metadata.attributes = attributes;
181bond::Metadata MetadataInit(
const T& default_value,
const char* name)
183 bond::Metadata metadata;
185 metadata.name = name;
186 detail::VariantSet(metadata.default_value, default_value);
191bond::Metadata MetadataInit(
const T& default_value,
const char* name, bond::Modifier modifier,
const Attributes& attributes)
193 bond::Metadata metadata = MetadataInit(name, modifier, attributes);
195 detail::VariantSet(metadata.default_value, default_value);
204bond::Metadata MetadataInit(
const nothing&,
const char* name)
206 bond::Metadata metadata;
208 metadata.name = name;
209 metadata.default_value.nothing =
true;
214bond::Metadata MetadataInit(
const nothing&,
const char* name, bond::Modifier modifier,
const Attributes& attributes)
216 bond::Metadata metadata = MetadataInit(name, modifier, attributes);
218 metadata.default_value.nothing =
true;
226bond::Metadata MetadataInit(
const char* name,
const char* qual_name,
const Attributes& attributes)
228 bond::Metadata metadata;
230 metadata.name = name;
231 metadata.qualified_name = qual_name;
232 metadata.attributes = attributes;
239template <
typename Params>
240bond::Metadata MetadataInit(
const char* name,
const char* qual_name,
const Attributes& attributes)
242 bond::Metadata metadata = MetadataInit(name, qual_name, attributes);
249 typedef typename boost::mpl::transform<Params, std::add_pointer<_> >::type ParamsPtr;
251 boost::mpl::for_each<ParamsPtr>(detail::TypeListBuilder(params));
253 metadata.name +=
"<" + params +
">";
254 metadata.qualified_name +=
"<" + params +
">";
262const reflection::nothing nothing = {};
264template <
typename T,
typename Iter>
struct
266 : std::integral_constant<uint16_t, boost::mpl::deref<Iter>::type::id> {};
268template <
typename T>
struct
269field_id<T, typename boost::mpl::end<T>::type>
270 : std::integral_constant<uint16_t, invalid_field_id> {};
273template <
typename T, u
int16_t minId = 0>
struct
277 template <
typename Field>
struct
279 : std::integral_constant<bool,
281 && std::is_same<typename Field::field_modifier, typename reflection::required_field_modifier>::value> {};
284 BOND_STATIC_CONSTEXPR uint16_t value = field_id<T, typename boost::mpl::find_if<T, is_next_required<_> >::type>::value;
291template <
typename T,
typename Enable =
void>
struct
293 : std::false_type {};
295template <
typename T>
struct
297#ifdef BOND_NO_SFINAE_EXPR
298 typename boost::enable_if<check_method<void (T::*)(
const Metadata&, bool), &T::WriteStructBegin> >::type>
300 detail::mpl::void_t<
decltype(std::declval<T>().WriteStructBegin(
301 std::declval<Metadata>(),
302 std::declval<bool>()))>>
308inline typename T::base*
315template <
typename T>
struct
322template <
typename T,
typename Reader>
struct
323remove_bonded<bonded<T, Reader> >
325 typedef typename remove_bonded<T>::type type;
329template <
typename T>
struct
335template <
typename T,
typename Reader>
struct
336remove_bonded_value<bonded<T, Reader> >
341template <
typename T,
typename Reader>
struct
342remove_bonded_value<value<T, Reader> >
348template <
typename T>
struct
350 : std::integral_constant<bool,
351 is_bonded<typename std::remove_const<T>::type>::value
352 || has_schema<typename std::remove_const<T>::type>::value> {};
357template <
typename Unused>
struct
358schema<Unknown, Unused>
362 typedef no_base base;
363 typedef boost::mpl::list<>::type fields;
364 static const Metadata metadata;
373template <
typename Unused>
374const Metadata schema<Unknown, Unused>::type::metadata
375 = reflection::MetadataInit(
"Unknown",
"Unknown", reflection::Attributes());
377template <
typename T,
typename Enable>
struct
378schema_for_passthrough
379 : schema<typename remove_bonded<T>::type>
382template <
typename T>
struct
383schema_for_passthrough<T, typename boost::disable_if<has_schema<typename remove_bonded<T>::type> >::type>
387 typedef typename schema<Unknown>::type type;
390template <
typename T>
struct
392 : std::integral_constant<bool,
393 is_list_container<typename std::remove_const<T>::type>::value
394 || is_set_container<typename std::remove_const<T>::type>::value
395 || is_map_container<typename std::remove_const<T>::type>::value> {};
398template <
typename Field,
typename Transform,
typename Enable =
void>
struct
400 : std::false_type {};
403template <
typename Field,
typename Transform>
struct
404is_fast_path_field<Field, Transform,
typename boost::enable_if<std::is_same<
typename Field::struct_type,
405 typename Transform::FastPathType> >::type>
409template <
typename T>
struct
411 : is_bond_type<typename T::field_type> {};
414template <
typename T>
struct
416 : has_schema<typename T::field_type> {};
419template <
typename T1,
typename T2,
typename Enable =
void>
struct
421 : std::false_type {};
424template <
typename T1,
typename T2>
struct
426 : std::integral_constant<bool,
427 (is_string<T1>::value && is_string<T2>::value)
428 || (is_wstring<T1>::value && is_wstring<T2>::value)
429 || ((
sizeof(T1) <=
sizeof(T2))
430 && ((std::is_unsigned<T1>::value && std::is_unsigned<T2>::value)
431 || (is_signed_int_or_enum<T1>::value && is_signed_int_or_enum<T2>::value)))> {};
434template <
typename T>
struct
435is_matching_basic<typename aliased_type<T>::type, T>
439template <
typename T1,
typename T2>
struct
441 : std::integral_constant<bool,
442 (is_bond_type<T1>::value && is_bond_type<T2>::value)
443 || (is_matching_basic<T1, T2>::value)
444 || (is_matching_container<T1, T2>::value)> {};
447template <
typename T>
struct
448is_matching_basic<T, T>
453is_matching_basic<bool, bool>
457template <
typename T>
struct
458is_matching_basic<bool, T>
459 : std::false_type {};
463is_matching_basic<uint8_t, bool>
464 : std::false_type {};
468is_matching_basic<float, double>
472template <
typename T,
typename Enable>
struct
476template <
typename T1,
typename T2>
struct
477is_matching_container<T1, T2,
478 typename boost::enable_if_c<is_container<T1>::value
479 && get_type_id<T1>::value == get_type_id<T2>::value>::type>
480 : is_matching<typename element_type<T1>::type,
481 typename element_type<T2>::type> {};
485template <
typename T1,
typename T2,
typename U1,
typename U2>
struct
486is_matching<std::pair<T1, T2>, std::pair<U1, U2> >
487 : std::integral_constant<bool,
488 is_matching<T1, U1>::value
489 && is_matching<T2, U2>::value> {};
492template <
typename T1,
typename T2>
struct
493is_matching<std::pair<T1, T2>, std::pair<T1, T2> >
498template <
typename T1,
typename Reader,
typename T2>
struct
499is_matching<value<T1, Reader>, T2>
500 : is_matching<T1, T2> {};
504template <
typename T,
typename Reader>
struct
505is_matching<value<void, Reader>, T>
506 : is_container<T> {};
509template <
typename T,
typename X,
typename Enable =
void>
struct
511 : std::false_type {};
514template <
typename T,
typename X>
struct
515is_element_matching<T, X, typename boost::enable_if<is_container<X> >::type>
516 : is_matching<T, typename element_type<X>::type> {};
519template <
typename X,
typename Reader>
struct
520is_element_matching<value<void, Reader>, X,
typename boost::enable_if<is_container<X> >::type>
521 : std::integral_constant<bool,
522 is_bond_type<typename element_type<X>::type>::value
523 || is_container<typename element_type<X>::type>::value> {};
526template <
typename T,
typename X,
typename Enable =
void>
struct
527is_map_element_matching
528 : std::false_type {};
531template <
typename X,
typename T>
struct
532is_map_element_matching<T, X, typename boost::enable_if<is_map_container<X> >::type>
533 : is_matching<T, typename element_type<X>::type::second_type> {};
536template <
typename X,
typename Reader>
struct
537is_map_element_matching<value<void, Reader>, X,
typename boost::enable_if<is_map_container<X> >::type>
538 : std::integral_constant<bool,
539 is_bond_type<typename element_type<X>::type::second_type>::value
540 || is_container<typename element_type<X>::type::second_type>::value> {};
543template <
typename T,
typename X,
typename Enable =
void>
struct
545 : std::false_type {};
548template <
typename T,
typename X>
struct
549is_map_key_matching<T, X, typename boost::enable_if<is_map_container<X> >::type>
550 : is_matching<T, typename element_type<X>::type::first_type> {};
553template <
typename T>
struct
555 : std::integral_constant<bool,
556 !(is_container<T>::value || is_bond_type<T>::value)> {};
560 : std::false_type {};
564template <
typename T,
typename Enable =
void>
struct
566 : std::false_type {};
568template <
typename T>
struct
569is_nested_container<T, typename boost::enable_if<is_map_container<T> >::type>
570 : std::integral_constant<bool,
571 !is_basic_type<typename element_type<T>::type::second_type>::value> {};
574template <
typename T>
struct
575is_nested_container<T, typename boost::enable_if<is_list_container<T> >::type>
576 : std::integral_constant<bool,
577 !is_basic_type<typename element_type<T>::type>::value> {};
580template <
typename T,
typename Enable =
void>
struct
582 : std::false_type {};
584template <
typename T>
struct
585is_struct_container<T, typename boost::enable_if<is_map_container<T> >::type>
586 : std::integral_constant<bool,
587 has_schema<typename element_type<T>::type::second_type>::value
588 || is_struct_container<typename element_type<T>::type::second_type>::value> {};
592template <
typename T>
struct
593is_struct_container<T, typename boost::enable_if<is_list_container<T> >::type>
594 : std::integral_constant<bool,
595 has_schema<typename element_type<T>::type>::value
596 || is_struct_container<typename element_type<T>::type>::value> {};
600template <
typename T>
struct
601is_struct_container_field
602 : is_struct_container<typename T::field_type> {};
606template <
typename T,
typename Enable =
void>
struct
608 : std::false_type {};
610template <
typename T>
struct
611is_basic_container<T, typename boost::enable_if<is_map_container<T> >::type>
612 : is_basic_type<typename element_type<T>::type::second_type> {};
614template <
typename T>
struct
615is_basic_container<T, typename boost::enable_if<is_list_container<T> >::type>
616 : is_basic_type<typename element_type<T>::type> {};
618template <
typename T>
struct
619is_basic_container<T, typename boost::enable_if<is_set_container<T> >::type>
623template <
typename T,
typename F>
struct
624is_matching_container_field
625 : is_matching_container<T, typename F::field_type> {};
628template <
typename T>
struct
630 : is_container<typename T::field_type> {};
633template <
typename T,
typename F>
struct
634is_matching_basic_field
635 : is_matching_basic<T, typename F::field_type> {};
638template <
typename T,
typename Reader>
struct
639is_basic_type<value<T, Reader> >
640 : std::false_type {};
643template <
typename T1,
typename T2>
struct
644is_basic_type<std::pair<T1, T2> >
645 : std::false_type {};
648template <
typename T,
typename X,
typename Enable =
void>
struct
650 : boost::mpl::copy_if<typename schema<T>::type::fields,
651 is_matching_basic_field<X, _>,
652 boost::mpl::front_inserter<boost::mpl::list<> > >
654 BOOST_STATIC_ASSERT((is_basic_type<X>::value));
658template <
typename T,
typename X>
struct
659matching_fields<T, X, typename boost::enable_if<is_container<X> >::type>
660 : boost::mpl::copy_if<typename schema<T>::type::fields,
661 is_matching_container_field<X, _>,
662 boost::mpl::front_inserter<boost::mpl::list<> > > {};
665template <
typename T>
struct
667 : boost::mpl::copy_if<typename schema<T>::type::fields,
669 boost::mpl::front_inserter<boost::mpl::list<> > > {};
672template <
typename T>
struct
674 : boost::mpl::copy_if<typename schema<T>::type::fields,
676 boost::mpl::front_inserter<boost::mpl::list<> > > {};
679template <
typename T>
struct
681 : boost::mpl::copy_if<typename schema<T>::type::fields,
682 is_container_field<_>,
683 boost::mpl::front_inserter<boost::mpl::list<> > > {};
686template <
typename T>
struct
688 : has_schema<typename schema<T>::type::base> {};
695 return get_type_id<T>::value;
699template <
typename Reader>
701GetTypeId(
const value<void, Reader>& value)
703 return value.GetTypeId();
707template <
typename T,
typename Reader>
struct
708get_type_id<value<T, Reader> >
712template <
typename T1,
typename T2>
struct
713get_type_id<std::pair<T1, T2> >
715 static const std::pair<BondDataType, BondDataType> value;
718template <
typename T1,
typename T2>
719const std::pair<BondDataType, BondDataType>
720get_type_id<std::pair<T1, T2> >::value = std::make_pair(
721 get_type_id<
typename std::remove_const<T1>::type>::value,
722 get_type_id<T2>::value);
726 : std::integral_constant<BondDataType, BT_BOOL> {};
730 : std::integral_constant<BondDataType, BT_UINT8> {};
734 : std::integral_constant<BondDataType, BT_UINT16> {};
738 : std::integral_constant<BondDataType, BT_UINT32> {};
742 : std::integral_constant<BondDataType, BT_UINT64> {};
746 : std::integral_constant<BondDataType, BT_INT8> {};
750 : std::integral_constant<BondDataType, BT_INT16> {};
754 : std::integral_constant<BondDataType, BT_INT32> {};
758 : std::integral_constant<BondDataType, BT_INT64> {};
762 : std::integral_constant<BondDataType, BT_FLOAT> {};
766 : std::integral_constant<BondDataType, BT_DOUBLE> {};
770 : std::integral_constant<BondDataType, BT_UNAVAILABLE> {};
772template <
typename T>
struct
773get_type_id<T, typename boost::enable_if<std::is_enum<T>>::type>
774 : get_type_id<int32_t> {};
776template <
typename T>
struct
777get_type_id<T, typename boost::enable_if<is_bond_type<T>>::type>
778 : std::integral_constant<BondDataType, BT_STRUCT> {};
780template <
typename T>
struct
781get_type_id<T, typename boost::enable_if<is_set_container<typename std::remove_const<T>::type>>::type>
782 : std::integral_constant<BondDataType, BT_SET> {};
784template <
typename T>
struct
785get_type_id<T, typename boost::enable_if<is_map_container<typename std::remove_const<T>::type>>::type>
786 : std::integral_constant<BondDataType, BT_MAP> {};
788template <
typename T>
struct
789get_type_id<T, typename boost::enable_if<is_list_container<typename std::remove_const<T>::type>>::type>
790 : std::integral_constant<BondDataType, BT_LIST> {};
792template <
typename T>
struct
793get_type_id<T, typename boost::enable_if<is_string<typename std::remove_const<T>::type>>::type>
794 : std::integral_constant<BondDataType, BT_STRING> {};
796template <
typename T>
struct
797get_type_id<T, typename boost::enable_if<is_wstring<typename std::remove_const<T>::type>>::type>
798 : std::integral_constant<BondDataType, BT_WSTRING> {};
800template <
typename T,
typename Enable>
struct
802 : get_type_id<typename aliased_type<T>::type> {};
805template <
typename T,
typename Enable =
void>
struct
807 : std::integral_constant<ListSubType, NO_SUBTYPE> {};
809template <
typename T>
struct
810get_list_sub_type_id<nullable<T> >
811 : std::integral_constant<ListSubType, NULLABLE_SUBTYPE> {};
814get_list_sub_type_id<blob>
815 : std::integral_constant<ListSubType, BLOB_SUBTYPE> {};
822 Init(uint32_t* _sizeof)
826 template <
typename T>
827 void operator()(
const T&)
829 _sizeof[get_type_id<T>::value] =
sizeof(T);
836 typedef boost::mpl::list
839 uint8_t, uint16_t, uint32_t, uint64_t,
840 int8_t, int16_t, int32_t, int64_t
843 PrimitiveTypes(uint32_t* _sizeof)
845 boost::mpl::for_each<type>(Init(_sizeof));
namespace bond
Definition: apply.h:17
Field description in compile-time schema.
Definition: reflection.h:73
static value_type & GetVariable(struct_type &object)
Static method returning reference to the field value for a particular object.
Definition: reflection.h:115
static const field_pointer field
Static data member representing the field pointer.
Definition: reflection.h:101
Struct struct_type
Type of the field's parent struct.
Definition: reflection.h:78
FieldType value_type
Type of the field value.
Definition: reflection.h:87
static const value_type & GetVariable(const struct_type &object)
Static method returning const reference to the field value for a particular object.
Definition: reflection.h:108
FieldType Struct::* field_pointer
Type of the field pointer.
Definition: reflection.h:81
ModifierTag field_modifier
Modifier tag for the field.
Definition: reflection.h:95
remove_maybe< FieldType >::type field_type
Type of the field.
Definition: reflection.h:84
static const Metadata & metadata
Static data member describing field metadata.
Definition: reflection.h:98