/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef THRIFT_FATAL_REFLECTION_H_ #define THRIFT_FATAL_REFLECTION_H_ 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { /** * READ ME FIRST: this file is divided into sections for each specific * reflection API. * * To quickly navigate this file, look for the string "SECTION: " without the * quotes. * * Note that the compile-time reflection API depends on metadata that's * generated by the Thrift compiler. In order to have this metadata available, * there are three simple but necessary steps: * * - enable code generation for `cpp2` as the target language; * - enable `reflection` as one of the `thrift_cpp2_options` flags; * - include the appropriate file containing the metadata (say your module is * defined in `some_dir/Module.thrift`, corresponding files can be included * from `some_dir/gen-cpp2/`): * * - Module_fatal.h: general module metadata * - Module_fatal_struct.h: metadata for all structures * - Module_fatal_enum.h: metadata for all enumerations * - Module_fatal_union.h: metadata for all variants (Thrift unions) * - Module_fatal_types.h: convenience header that includes metadata for * modules, structures, enumerations and variants * - Module_fatal_all.h: convenience header that includes all the * metadata generated by the Thrift compiler * * Thrift breaks the metadata up in several files to help reduce compilation * times by including only what's needed. * * @author: Marcelo Juchem */ ////////////////////////////////////////////// // SECTION: IMPORTANT NOTES AND CONVENTIONS // ////////////////////////////////////////////// /** * NOTE ON COMPILE-TIME STRINGS: many strings found in the Thrift file are * converted to compile-time strings in the form of a `fatal::sequence` * of `char`. * * They are often represented as general C++ identifiers. Not all strings are * directly representable as C++ identifiers though, given that not all * characters are accepted as identifier names, only [_a-zA-Z0-9]. When that's * the case, the invalid characters are replaced by an underscode (_). * * Names starting with numbers are prefixed with 's_'. For example, the string * "42 is it" could be represented by the identifier 's_42_is_it'. * * Collisions are solved by appending a positive integer starting at 1 and * growing by 1 per collision, in the order the identifiers appear. For * instance, say there are three strings "a_", "a " and "a.". "a_" could be * represented by the identifier 'a_' while "a " could be represented by 'a_1' * and "a." could be 'a_2'. * * @author: Marcelo Juchem */ //////////////////////////////////////////// // SECTION: TYPE ALIASES AND ENUMERATIONS // //////////////////////////////////////////// /** * An alias to the type used by Thrift as a struct's field ID. * * @author: Marcelo Juchem */ using field_id_t = std::int16_t; /** * An alias to the type used by Thrift as a type's unique identifier. * * NOTE: this is a legacy feature and should be avoided on new code. * * @author: Marcelo Juchem */ using legacy_type_id_t = std::uint64_t; /** * Represents whether a field is required to be set in a given structure or not. * * @author: Marcelo Juchem */ enum class optionality { /** * Field is required. * * @author: Marcelo Juchem */ required, /** * Field is optional. * * @author: Marcelo Juchem */ optional, /** * Field is optional on the reading side but required on the writing side. * * @author: Marcelo Juchem */ required_of_writer, /** * Field has terse write semantics. * * @author: Marcelo Juchem */ terse, }; ///////////////////////////// // SECTION: TYPE CLASS API // ///////////////////////////// /** * Returns the type class of a thrift class, which is either a structure, a * variant, or an exception. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * typedef list MyList; * * ///////////// * // foo.cpp // * ///////////// * * // yields `type_class::structure` * using result1 = reflect_type_class_of_thrift_class; * * // yields `type_class::variant` * using result1 = reflect_type_class_of_thrift_class; * * // yields `type_class::unknown` * using result2 = reflect_type_class_of_thrift_class; * * // yields `type_class::unknown` * using result3 = reflect_type_class_of_thrift_class; * * // yields `type_class::unknown` * using result4 = reflect_type_class_of_thrift_class; */ template using reflect_type_class_of_thrift_class = typename detail::reflect_type_class_of_thrift_class_impl::type; /** * Returns the type class of a thrift class, which is either a structure, a * variant, or an exception, or of a thrift enum. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * typedef list MyList; * * ///////////// * // foo.cpp // * ///////////// * * // yields `type_class::structure` * using result1 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::variant` * using result1 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::enumeration` * using result2 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::unknown` * using result3 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::unknown` * using result4 = reflect_type_class_of_thrift_class_enum; */ template using reflect_type_class_of_thrift_class_enum = typename detail::reflect_type_class_of_thrift_class_enum_impl::type; /** * Returns the type class of a thrift class, which is either a structure, a * variant, or an exception, or of a thrift enum. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * typedef list MyList; * * ///////////// * // foo.cpp // * ///////////// * * // yields `type_class::structure` * using result1 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::variant` * using result1 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::enumeration` * using result2 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::unknown` * using result3 = reflect_type_class_of_thrift_class_enum; * * // yields `type_class::unknown` * using result4 = reflect_type_class_of_thrift_class_enum; */ template using reflect_type_class_of_thrift_class_enum = typename detail::reflect_type_class_of_thrift_class_enum_impl::type; ///////////////////////// // SECTION: MODULE API // ///////////////////////// /** * Holds reflection metadata for stuff defined in a Thrift file. * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * @author: Marcelo Juchem */ template struct reflected_module { /** * The name. * * A `fatal::constant_sequence` (compile-time string) representing the module * name. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * struct MyStruct {} * * // C++ * * using info = reflect_module; * using name = typename info::name; * // yields `fatal::constant_sequence< * // char, 'M', 'y', 'M', 'o', 'd', 'u', 'l', 'e', * // >` */ using name = typename Traits::name; /** * The map from language to namespace. * * A `fatal::list` of `fatal::pair` where the key is a `fatal::sequence` * (compile-time string) representing the language, associated with a * compile-time string representing the namespace. * * Example: * * // MyModule.thrift * * namespace cpp My.NamespaceCpp * namespace cpp2 My.Namespace * namespace java My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * // C++ * * using info = reflect_module; * * FATAL_S(cpp, "cpp"); * FATAL_S(cpp2, "cpp2"); * FATAL_S(java, "java"); * * // yields `fatal::sequence< * // char, * // 'M', 'y', ':', ':', 'N', 'a', 'm', 'e', * // 's', 'p', 'a', 'c', 'e', 'C', 'p', 'p' * // >` * using result1 = fatal::get; * * // yields `fatal::sequence< * // char, 'M', 'y', ':', ':', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e' * // >` * using result2 = fatal::get; * * // yields `fatal::sequence< * // char, 'M', 'y', '.', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e' * // >` * using result3 = fatal::get; * * @author: Marcelo Juchem */ using namespaces = typename Traits::namespaces; /** * The list of enumerations with reflection metadata available. * * A `fatal::list` of `fatal::pair` where the first type is the one generated * by the Thrift compiler for each enumeration, and the second one is the * compile-time string (`fatal::sequence`) representing the enumeration name. * * Use `fatal::enum_traits` to retrieve reflection information for each * enumeration (fatal/type/enum.h). * * @author: Marcelo Juchem */ using enums = typename Traits::enums; /** * The list of unions with reflection metadata available. * * A `fatal::list` of `fatal::pair` where the first type is the one generated * by the Thrift compiler for each union, and the second one is the * compile-time string (`fatal::sequence`) representing the union name. * * Use `fatal::variant_traits` to retrieve reflection information for each * union (fatal/type/variant_traits.h). * * @author: Marcelo Juchem */ using unions = typename Traits::unions; /** * The list of structs with reflection metadata available. * * A `fatal::list` of `fatal::pair` where the first type is the one generated * by the Thrift compiler for each struct, and the second one is the * compile-time string (`fatal::sequence`) representing the struct name. * * @author: Marcelo Juchem */ using structs = typename Traits::structs; /** * The list of services with reflection metadata available. * * A `fatal::list` of compile-time strings * (`fatal::sequence`) representing each service name. * * @author: Marcelo Juchem */ using services = typename Traits::services; }; /** * Retrieves reflection metadata (as a `reflected_module`) associated with the * given reflection metadata tag. * * The Thrift compiler generates a reflection metadata tag for each Thrift file * named `namespace::thriftfilename_tags::module`. * * If the given tag does not represent a Thrift module, or if there's no * reflection metadata available for it, compilation will fail. * * See the documentation on `reflected_module` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * enum MyEnum1 { a, b, c } * enum MyEnum2 { x, y, x } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_module; * * // yields `2` * auto result1 = info::enums::size; * * // fails compilation * using result2 = reflect_module; * * @author: Marcelo Juchem */ template using reflect_module = fatal:: registry_lookup; /** * Retrieves reflection metadata (as a `reflected_module`) associated with the * given reflection metadata tag. * * The Thrift compiler generates a reflection metadata tag for each Thrift file * named `namespace::thriftfilename_tags::module`. * * If the given tag does not represent a Thrift module, or if there's no * reflection metadata available for it, `Default` will be returned.s If * `Default` is not specified, it defaults to void. * * See the documentation on `reflected_module` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * enum MyEnum1 { a, b, c } * enum MyEnum2 { x, y, x } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = try_reflect_module< * My::Namespace::MyModule_tags::module, * void * >; * * // yields `2` * auto result1 = info::enums::size; * * // yields `void` * using result2 = try_reflect_module; * * @author: Marcelo Juchem */ template using try_reflect_module = fatal::try_registry_lookup< apache::thrift::detail::reflection_metadata_tag, Tag, Default>; /** * Tells whether the given type is a tag that represents the reflection metadata * of the types declared in a Thrift file. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * ///////////// * // foo.cpp // * ///////////// * * // yields `std::true_type` * using result1 = is_reflectable_module; * * // yields `std::false_type` * using result2 = is_reflectable_module; * * // yields `std::false_type` * using result3 = is_reflectable_module; * * @author: Marcelo Juchem */ template using is_reflectable_module = std::integral_constant< bool, !std::is_same, void>::value>; /** * Gets the reflection metadata tag for the Thrift file where the type `T` is * declared. * * The type `T` must be either a struct, enum or union. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * // C++ * * // yields `My::Namespace::MyModule_tags::module` * using result1 = reflect_module_tag; * * // yields `My::Namespace::MyModule_tags::module` * using result2 = reflect_module_tag; * * @author: Marcelo Juchem */ template using reflect_module_tag = typename apache::thrift::detail::reflect_module_tag_selector< reflect_type_class_of_thrift_class_enum, T, false>::type; /** * Tries to get the reflection metadata tag for the Thrift file where the type * `T` is declared. * e: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * // C++ * * // yields `My::Namespace::MyModule_tags::module` * using result1 = reflect_module_tag; * * // yields `My::Namespace::MyModule_tags::module` * using result2 = reflect_module_tag; * * // yields `void` * using result3 = reflect_module_tag; * * @author: Marcelo Juchem */ template using try_reflect_module_tag = typename apache::thrift::detail::reflect_module_tag_selector< reflect_type_class_of_thrift_class_enum, T, true, Default>::type; /** * Represents an annotation from `reflected_annotations::map`. * * For the examples below, consider code generated for this Thrift file: * * struct Foo { * 1: i32 z * } ( * a = '{not a valid format}', * b = '{"valid": "format", "foo": 10, "bar": true, "x": [-5, 0, 5]}', * c = '"hello"' * } * * @author: Marcelo Juchem */ template struct annotation { /** * Represents the annotation key as a compile-time string, in the form of a * `fatal::sequence` of type `char`. * * @author: Marcelo Juchem */ using key = Key; /** * Represents the annotation value as a compile-time string, in the form of a * `fatal::sequence` of type `char`. * * @author: Marcelo Juchem */ using value = Value; }; /** * Holds reflection metadata for annotations. * * For the examples below, consider code generated for this Thrift file: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } ( * some.annotation = "some value", * another.annotation = "another value", * ) * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * @author: Marcelo Juchem */ template struct reflected_annotations { /** * An implementation defined type that provides the names for each annotation * key as a member type alias named after the key. * * These type aliases are used as the key for the `map` member. * * Look for 'NOTE ON COMPILE-TIME STRINGS' for how the strings are converted * to C++ identifiers - caveat: instead of using the order they appear as the * precedence for collision resolution, it uses lexicographical order of the * keys. * * Example: * * using annotations = reflect_struct::annotations; * * // yields `fatal::sequence` * using result1 = annotations::keys::some_annotation; * * @author: Marcelo Juchem */ using keys = typename Metadata::keys; /** * An implementation defined type that provides the names for each annotation * value as a member type alias named after the key. * * These type aliases are used as the value for the `map` member. * * Look for 'NOTE ON COMPILE-TIME STRINGS' for how the strings are converted * to C++ identifiers - caveat: instead of using the order they appear as the * precedence for collision resolution, it uses lexicographical order of the * keys. * * Example: * * using annotations = reflect_struct::annotations; * * // yields `fatal::sequence` * using result1 = annotations::values::some_annotation; * * @author: Marcelo Juchem */ using values = typename Metadata::values; /** * A list of `annotation` representing the annotations declared in the Thrift * file, sorted by keys. * * See the `annotation` type for more information. * * Example: * * // yields an instantiation of the `reflected_annotations` template * using annotations = reflect_struct::annotations; * * FATAL_S(key, "another.annotation"); * * // yields `fatal::sequence` * using result1 = fatal::get::value; * * // yields `fatal::sequence` * using result2 = fatal::get< * annotations::map, * annotations::keys::some_annotation * >::value; * * @author: Marcelo Juchem */ using map = typename Metadata::map; }; //////////////////////////// // SECTION: STRUCTURE API // //////////////////////////// /** * Holds reflection metadata for a given struct. * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * For the examples below, consider code generated for this Thrift file: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c ( * member.note = "member text", * another.member.note = "another member text", * ) * } ( * some.annotation = "some value", * another.annotation = "another value", * ) * * @author: Marcelo Juchem */ template struct reflected_struct { /** * A type alias for the struct itself. * * Example: * * using info = reflect_struct; * * // yields `MyStruct` * using result = info::type; * * @author: Marcelo Juchem */ using type = typename Traits::type; /** * A compile-time string representing the struct name. * * Example: * * using info = reflect_struct; * * // yields `fatal::sequence< * // char, * // 'M', 'y', 'S', 't', 'r', 'u', 'c', 't' * // >` * using result = info::name; * * @author: Marcelo Juchem */ using name = typename Traits::name; /** * The reflection metadata tag for the Thrift file where this structure is * declared. * * Example: * * using info = reflect_struct; * * // yields `My::Namespace::MyModule_tags::module` * using result = info::module; * * @author: Marcelo Juchem */ using module = typename Traits::metadata::module; /** * An implementation defined type template that provides the appropriate * `reflected_struct_data_member` for each data member as a member type alias * with the same name. * * These type aliases are used as the type mapped by the `members` member * offered by the `reflected_struct` class. * * An optional transform can be specified, which will be applied on top of the * members' `reflected_struct_data_member`. * * Example: * * using info = reflect_struct; * * // yields `fatal::sequence` * using result1 = info::member::a::name; * * // yields `std::int32_t` * using result2 = info::member::a::type; * * // yields `1` * using result3 = info::member::a::id::value; * * @author: Marcelo Juchem */ using member = typename Traits::member; /** * A `fatal::list` of `reflected_struct_data_member` representing each member. * * See the documentation for `reflected_struct_data_member` (below) for more * information on its members. * * Example: * * struct visitor { * template * void operator ()(fatal::tag) { * using name = typename MemberInfo::name; * std::cout << "- member: " << fatal::z_data() << '\n'; * } * }; * * using info = reflect_struct; * * // prints the names of all members of `MyStruct` * fatal::foreach(visitor()); * * @author: Marcelo Juchem */ using members = typename Traits::members; /** * An instantiation of `reflected_annotations` representing the annotations * declared for this type in the Thrift file. * * Example: * * using info = reflect_struct; * * // yields `fatal::sequence` * using result = info::annotations::values::another_annotation; * * @author: Marcelo Juchem */ using annotations = typename Traits::metadata::annotations; /** * An implementation defined type that provides the annotations for each * member of the struct. Each member's annotations are represented by an * instance of `reflected_annotations` named after the member itself. * * Example: * * using info = reflect_struct; * * // yields `fatal::sequence` * using result1 = info::members_annotations::c::values::member_note * * @author: Marcelo Juchem */ using members_annotations = typename Traits::members_annotations; /** * A unique identifier generated by thrift for this structure. * * NOTE: this is a legacy feature and should be avoided on new code. * * @author: Marcelo Juchem */ using legacy_id = typename Traits::metadata::legacy_id; }; /** * Holds reflection metadata for a given struct's data member. * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * @author: Marcelo Juchem */ template struct reflected_struct_data_member { /** * A `fatal::sequence` of `char` representing the data member name as * a compile-time string. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using member = info::member::fieldC; * * // yields `fatal::sequence` * using result1 = member::name; * * // yields "fieldC" * auto result2 = fatal::z_data(); * * @author: Marcelo Juchem */ using name = typename Traits::name; /** * The type of the data member. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using member = info::member::fieldC; * * // yields `double` * using result1 = member::type; * * @author: Marcelo Juchem */ using type = typename Traits::type; /** * A tag type representing the name of this member. */ using tag = typename Traits::tag; /** * A `std::integral_constant` of type `field_id_t` representing the Thrift * field id for the data member. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using member = info::member::fieldC; * * // yields `std::integral_constant` * using result1 = member::id; * * // yields `3` * auto result2 = result1::value; * * @author: Marcelo Juchem */ using id = std::integral_constant; /** * A `std::integral_constant` of type `optionality` representing whether a * field is qualified as required or optional. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: required i32 fieldA * 2: optional string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using a = info::member::fieldA; * using b = info::member::fieldB; * using c = info::member::fieldC; * * // yields `std::integral_constant` * using result1 = a::required; * * // yields `std::integral_constant` * using result2 = b::required; * * // yields `std::integral_constant< * // optionality, * // optionality::required_of_writer * // >` * using result3 = c::required; * * @author: Marcelo Juchem */ using optional = std::integral_constant; /** * A type that works as a getter for the data member. * * See also Fatal's documentation on `FATAL_DATA_MEMBER_GETTER` in * `fatal/type/traits.h` for more information on how to make the most out of * the data member getter. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using member = info::member::fieldC; * using getter = member::getter; * * MyStruct pod; * * pod.fieldC = 7.2; * * // yields `7.2` * auto result1 = getter{}(pod); * * // sets `5.6` on `pod.fieldC` * getter{}(pod) = 5.6; * * // yields `5.6` * auto result2 = pod.fieldC; * * @author: Marcelo Juchem */ using getter = typename Traits::getter; /** * Similar to getter, but return `(optional_)?field_ref` instead. */ using field_ref_getter = typename Traits::field_ref_getter; /** * The type class for this member. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC * } * * // C++ * * using info = reflect_struct; * using member = info::member::fieldC; * * // yields `type_class::floating_point` * using result1 = member::type_class; * * @author: Marcelo Juchem */ using type_class = typename Traits::type_class; /** * An instantiation of `reflected_annotations` representing the annotations * declared for this member in the Thrift file. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 fieldA * 2: string fieldB * 3: double fieldC (field.note = "some notes") * } * * // MyModule.cpp * * using info = reflect_struct; * using member = info::member::fieldC; * * // yields `fatal::sequence` * using result = member::annotations::values::field_note; * * @author: Marcelo Juchem */ using annotations = typename Traits::annotations; /** * Checks whether the member represented by this metadata is set in the given * object. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: optional i32 field * } * * // MyModule.cpp * * using info = reflect_struct; * using member = info::member::field; * * MyStruct pod; * * // yields `false` * bool result1 = member::is_set(pod); * * pod.set_field(42); * * // yields `true` * bool result2 = member::is_set(pod); * * @author: Marcelo Juchem */ template static constexpr inline bool is_set(T const& owner) { namespace impl = apache::thrift::detail::reflection_impl; return impl::is_set(field_ref_getter{}(owner)); } /** * Marks the member as being either set or not set on the parent object. * * Example: * * // MyModule.thrift * * namespace cpp2 My.Namespace * * struct MyStruct { * 1: optional i32 field * } * * // MyModule.cpp * * using info = reflect_struct; * using member = info::types::members; * * MyStruct pod; * * // mark `field` as being set * member::mark_set(pod, true) * * * @author: Dylan Knutson */ template static constexpr inline bool mark_set(T& owner, bool set) { namespace impl = apache::thrift::detail::reflection_impl; impl::mark_set(field_ref_getter{}(owner), set); return set; } }; /** * Retrieves reflection metadata (as a `reflected_struct`) associated with the * given struct. * * If the given type is not a Thrift struct, or if there's no reflection * metadata available for it, compilation will fail. * * See the documentation on `reflected_struct` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_struct; * * // yields `3` * auto result = fatal::size::value; * * @author: Marcelo Juchem */ template using reflect_struct = fatal:: registry_lookup; /** * Retrieves reflection metadata (as a `reflected_struct`) associated with the * given struct. * * If the given type is not a Thrift struct, or if there's no reflection * metadata available for it, `Default` will be returned. If `Default` is not * specified, it defaults to void. * * See the documentation on `reflected_struct` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_struct; * * // yields `3` * auto result = fatal::size::value; * * @author: Marcelo Juchem */ template using try_reflect_struct = fatal::try_registry_lookup< apache::thrift::detail::struct_traits_metadata_tag, Struct, Default>; /** * Tells whether the given type is a Thrift struct with compile-time reflection * support. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * struct MyStruct { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * ///////////// * // foo.cpp // * ///////////// * * // yields `std::true_type` * using result1 = is_reflectable_struct; * * // yields `std::false_type` * using result2 = is_reflectable_struct; * * // yields `std::false_type` * using result3 = is_reflectable_struct; * * @author: Marcelo Juchem */ template using is_reflectable_struct = std::integral_constant< bool, !std::is_same, void>::value>; ////////////////////////////// // SECTION: ENUMERATION API // ////////////////////////////// /** * Holds reflection metadata for a given enumeration. * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * For the examples below, consider code generated for this Thrift file: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * enum MyEnum { * a, b, c * } ( * some.annotation = "some value", * another.annotation = "another value", * ) * * @author: Marcelo Juchem */ template struct reflected_enum { /** * A type alias for the enumeration itself. * * Example: * * using info = reflect_enum; * * // yields `MyEnum` * using result = info::type; * * @author: Marcelo Juchem */ using type = T; /** * An alias to `fatal::enum_traits`. * * See `fatal::enum_traits`, from the Fatal library, for more information. * * Example: * * using info = reflect_enum; * using traits = info::traits; * * // yields "a" * auto result = traits::to_string(MyEnum::a); * * @author: Marcelo Juchem */ using traits = fatal::enum_traits; /** * The reflection metadata tag for the Thrift file where this enumeration is * declared. * * Example: * * using info = reflect_enum; * * // yields `My::Namespace::MyModule_tags::module` * using result = info::module; * * @author: Marcelo Juchem */ using module = typename traits::metadata::module; /** * An instantiation of `reflected_annotations` representing the annotations * declared for this type in the Thrift file. * * Example: * * using info = reflect_enum; * * // yields `fatal::sequence` * using result = info::annotations::values::another_annotation; * * @author: Marcelo Juchem */ using annotations = typename traits::metadata::annotations; /** * A unique identifier generated by thrift for this structure. * * NOTE: this is a legacy feature and should be avoided on new code. * * @author: Marcelo Juchem */ using legacy_id = typename traits::metadata::legacy_id; }; /** * Retrieves reflection metadata (as a `reflected_enum`) associated with the * given enumeration. * * If the given type is not a Thrift enumeration, or if there's no reflection * metadata available for it, compilation will fail. * * See the documentation on `reflected_enum` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * enum MyEnum { a, b, c } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_enum; * * // yields `MyEnum` * auto result = info::type; * * @author: Marcelo Juchem */ template using reflect_enum = reflected_enum; /** * Tells whether the given type is a Thrift enum with compile-time reflection * support. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * ///////////// * // foo.cpp // * ///////////// * * // yields `std::true_type` * using result1 = is_reflectable_enum; * * // yields `std::false_type` * using result2 = is_reflectable_enum; * * // yields `std::false_type` * using result3 = is_reflectable_enum; * * @author: Marcelo Juchem */ template using is_reflectable_enum = fatal::has_enum_traits; ////////////////////////////////// // SECTION: VARIANT (UNION) API // ////////////////////////////////// /** * Holds reflection metadata for a given union. * * NOTE: this class template is only intended to be instantiated by Thrift. * Users should ignore the template parameters taken by it and focus simply on * the members provided. * * For the examples below, consider code generated for this Thrift file: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } ( * some.annotation = "some value", * another.annotation = "another value", * ) * * @author: Marcelo Juchem */ template struct reflected_variant { /** * A type alias for the union itself. * * Example: * * using info = reflect_variant; * * // yields `MyUnion` * using result = info::type; * * @author: Marcelo Juchem */ using type = T; /** * An alias to `fatal::variant_traits`. * * See `fatal::variant_traits`, from the Fatal library, for more information. * * Example: * * using info = reflect_variant; * using traits = info::traits; * * // yields `MyUnion::Type::a` * auto result = traits::array::ids::data[0]; * * @author: Marcelo Juchem */ using traits = fatal::variant_traits; /** * The reflection metadata tag for the Thrift file where this union is * declared. * * Example: * * using info = reflect_variant; * * // yields `My::Namespace::MyModule_tags::module` * using result = info::module; * * @author: Marcelo Juchem */ using module = typename traits::metadata::module; /** * An instantiation of `reflected_annotations` representing the annotations * declared for this type in the Thrift file. * * Example: * * using info = reflect_variant; * * // yields `fatal::sequence` * using result = info::annotations::values::another_annotation; * * @author: Marcelo Juchem */ using annotations = typename traits::metadata::annotations; /** * A unique identifier generated by thrift for this structure. * * NOTE: this is a legacy feature and should be avoided on new code. * * @author: Marcelo Juchem */ using legacy_id = typename traits::metadata::legacy_id; /** * Gets the member descriptor for the field with given `Name`. * * See `fatal::variant_type_descriptor`, from the Fatal library, for more * information. * * Example: * * using id_traits = fatal::enum_traits; * using info = reflect_variant; * using member_info = info::by_name; * * MyUnion u; * u.set_a(10); * * // yields `10` * auto result = member_info::get(u); * * @author: Marcelo Juchem */ template using by_name = fatal::get< typename traits::descriptors, Name, apache::thrift::detail::reflection_impl::variant_member_name>; /** * Gets the member descriptor for the field with given `TypeId`. * * See `fatal::variant_type_descriptor`, from the Fatal library, for more * information. * * Example: * * using id_traits = fatal::enum_traits; * using info = reflect_variant; * using member_info = info::by_type_id; * * MyUnion u; * u.set_a(10); * * // yields `10` * auto result = member_info::get(u); * * @author: Marcelo Juchem */ template using by_type_id = fatal::get< typename traits::descriptors, std::integral_constant, fatal::get_type::id>; /** * Gets the member descriptor for the field with given `FieldId`. * * See `fatal::variant_type_descriptor`, from the Fatal library, for more * information. * * Example: * * using id_traits = fatal::enum_traits; * using info = reflect_variant; * using member_info = info::by_field_id<1>; * * MyUnion u; * u.set_a(10); * * // yields `10` * auto result = member_info::get(u); * * @author: Marcelo Juchem */ template using by_field_id = fatal::get< typename traits::descriptors, std::integral_constant, apache::thrift::detail::reflection_impl::variant_member_field_id>; }; /** * Retrieves reflection metadata (as a `reflected_variant`) associated with the * given union. * * If the given type is not a Thrift union, or if there's no reflection * metadata available for it, compilation will fail. * * See the documentation on `reflected_variant` (above) for more information on * the returned type. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_variant; * * // yields `MyUnion` * auto result = info::type; * * @author: Marcelo Juchem */ template using reflect_variant = reflected_variant; /** * Represents Thrift specific metadata for a given union's member. * * This is exposed as the metadata for Fatal's `variant_member_descriptor`. * * For the examples below, consider code generated for this Thrift file: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * Example: * * ////////////////// * // whatever.cpp // * ////////////////// * using info = reflect_variant; * using metadata = info::by_type::metadata; * * // yields "c" * auto result = fatal::z_data(); * * @author: Marcelo Juchem */ template struct reflected_variant_member_metadata { /** * A compile-time string representing the name of this member. * * Example: * * using info = reflect_variant; * * // yields "c" * auto result = fatal::z_data::metadata::name>(); * * @author: Marcelo Juchem */ using name = typename Traits::name; /** * A tag type representing the name of this member. */ using tag = typename Traits::tag; /** * A `std::integral_constant` of type `field_id_t` representing the Thrift * field id for this member. * * Example: * * using info = reflect_variant; * * // yields `3` * auto result = info::by_type::metadata::id::value; * * @author: Marcelo Juchem */ using id = std::integral_constant; /** * The type class for this member. * * Example: * * using info = reflect_variant; * * // yields `type_class::floating_point` * auto result = info::by_type::metadata::id; * * @author: Marcelo Juchem */ using type_class = typename Traits::type_class; }; /** * Tells whether the given type is a Thrift union with compile-time reflection * support. * * Example: * * ///////////////////// * // MyModule.thrift // * ///////////////////// * namespace cpp2 My.Namespace * * union MyUnion { * 1: i32 a * 2: string b * 3: double c * } * * enum MyEnum { a, b, c } * * ///////////// * // foo.cpp // * ///////////// * * // yields `std::true_type` * using result1 = is_reflectable_union; * * // yields `std::false_type` * using result2 = is_reflectable_union; * * // yields `std::false_type` * using result3 = is_reflectable_union; * * @author: Marcelo Juchem */ template using is_reflectable_union = fatal::has_variant_traits; } // namespace thrift } // namespace apache #include #endif // THRIFT_FATAL_REFLECTION_H_