#ifndef seafire__resources__traits_hxx_ #define seafire__resources__traits_hxx_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace seafire::resources::traits { // ============================================================================= // resources. // // is_gettable_resource // template> struct is_gettable_resource : std::false_type {}; template struct is_gettable_resource< R, std::void_t< decltype(&R::get) > > : std::bool_constant< std::is_same_v< void, typename common::traits::function_traits::return_type > || representation::traits::is_representation_v< typename common::traits::function_traits::return_type > > { }; template inline constexpr bool is_gettable_resource_v{is_gettable_resource::value}; template> struct get_traits { using result_type = void; }; template struct get_traits { using function_traits = common::traits::function_traits; using result_type = common::traits::remove_optional_t; }; // is_updatable_resource // template> struct is_updatable_resource : std::false_type {}; template struct is_updatable_resource< R, std::void_t< decltype(&R::update) > > : std::bool_constant< // Check if the first arg to R::update() is an input representation. representation::traits::is_input_representation_v< typename common::traits::first_arg::type > && ( // Check if return value of R::update() is void. std::is_same_v< void, typename common::traits::function_traits::return_type > || // Check if return value of R::update() is a gettable resource. is_gettable_resource_v< typename common::traits::function_traits::return_type > || // Check if return value of R::update() is a representation. representation::traits::is_representation_v< typename common::traits::function_traits::return_type > ) > { }; template inline constexpr bool is_updatable_resource_v{is_updatable_resource::value}; template> struct update_traits { using input_representation_type = void; using result_type = void; }; template struct update_traits { using function_traits = common::traits::function_traits; using input_representation_type = common::traits::first_arg_t; using result_type = typename function_traits::return_type; }; // is_creatable_resource // template> struct is_creatable_resource : std::false_type {}; template struct is_creatable_resource< R, std::void_t< decltype(&R::create) > > : std::bool_constant< representation::traits::is_input_representation_v< common::traits::first_arg_t > && ( // Check if return value of R::create() is void. std::is_same_v< void, typename common::traits::function_traits::return_type > || // Check if return value of R::create() is a gettable resource. is_gettable_resource_v< typename common::traits::function_traits::return_type > || // Check if return value of R::create() is a representation. representation::traits::is_representation_v< typename common::traits::function_traits::return_type > ) > { }; template inline constexpr bool is_creatable_resource_v{is_creatable_resource::value}; template> struct create_traits { using input_representation_type = void; using result_type = void; }; template struct create_traits { using function_traits = common::traits::function_traits; using input_representation_type = common::traits::first_arg_t; using result_type = typename function_traits::return_type; }; // is_erasable_resource // template> struct is_erasable_resource : std::false_type {}; template struct is_erasable_resource< R, std::void_t< decltype(std::declval().erase()) > > : std::true_type{ }; template constexpr bool is_erasable_resource_v{is_erasable_resource::value}; // is_resource // template struct is_resource : std::bool_constant< is_gettable_resource_v || is_updatable_resource_v || is_creatable_resource_v || is_erasable_resource_v > { }; template constexpr bool is_resource_v{is_resource::value}; // has_location // template> struct has_location : std::false_type {}; template struct has_location< R, std::void_t< decltype( code::uri::uri_t{ std::declval().location() } ) > > : std::true_type{ }; template constexpr bool has_location_v{has_location::value}; // resource_traits // template struct resource_traits { using resource_type = R; // properties // static constexpr bool has_entity_tag{ representation::traits::has_entity_tag_v }; static constexpr bool has_last_modified{ representation::traits::has_last_modified_v }; static constexpr bool has_location{ has_location_v }; static protocol::tokens_t allowed_methods() { protocol::tokens_t methods; if constexpr (is_gettable) { methods.emplace_back("GET"); methods.emplace_back("HEAD"); } if constexpr (is_updatable) methods.emplace_back("PUT"); if constexpr (is_creatable) methods.emplace_back("POST"); if constexpr (is_erasable) methods.emplace_back("DELETE"); return methods; } // GET // static constexpr bool is_gettable{ is_gettable_resource_v }; using get_traits = traits::get_traits; using get_representation_type = typename get_traits::result_type; using get_representation_type_traits = representation::traits::representation_traits< get_representation_type >; // UPDATE // static constexpr bool is_updatable{ is_updatable_resource_v }; using update_traits = traits::update_traits; using update_input_representation_type = typename update_traits::input_representation_type; using update_input_representation_type_traits = representation::traits::input_representation_traits; using update_result_type = typename update_traits::result_type; // CREATE // static constexpr bool is_creatable{ is_creatable_resource_v }; using create_traits = traits::create_traits; using create_input_representation_type = typename create_traits::input_representation_type; using create_input_representation_type_traits = representation::traits::input_representation_traits; using create_result_type = typename create_traits::result_type; // ERASE // static constexpr bool is_erasable{ is_erasable_resource_v }; }; } // namespace seafire::resources::traits #endif