317 lines
8.3 KiB
C++
317 lines
8.3 KiB
C++
#ifndef code__seafire__resources__traits_hxx_
|
|
#define code__seafire__resources__traits_hxx_
|
|
|
|
#include <code/seafire/common/traits.hxx>
|
|
#include <code/seafire/protocol/media-type.hxx>
|
|
#include <code/seafire/protocol/rfc7232/entity-tag.hxx>
|
|
#include <code/seafire/protocol/token.hxx>
|
|
#include <code/seafire/representation/traits.hxx>
|
|
|
|
#include <code/uri/uri.hxx>
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <optional>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
namespace code::seafire::resources::traits
|
|
{
|
|
|
|
// =============================================================================
|
|
// resources.
|
|
//
|
|
|
|
// is_gettable_resource<R>
|
|
//
|
|
|
|
template<typename, typename = std::void_t<>>
|
|
struct is_gettable_resource : std::false_type {};
|
|
|
|
template<typename R>
|
|
struct is_gettable_resource<
|
|
R,
|
|
std::void_t<
|
|
decltype(&R::get)
|
|
>
|
|
> : std::bool_constant<
|
|
std::is_same_v<
|
|
void,
|
|
typename common::traits::function_traits<decltype(&R::get)>::return_type
|
|
>
|
|
||
|
|
representation::traits::is_optional_representation_v<
|
|
typename common::traits::function_traits<decltype(&R::get)>::return_type
|
|
>
|
|
> {
|
|
};
|
|
|
|
template<typename R>
|
|
inline constexpr bool is_gettable_resource_v{is_gettable_resource<R>::value};
|
|
|
|
template<typename R, bool = is_gettable_resource_v<R>>
|
|
struct get_traits {
|
|
using result_type = void;
|
|
};
|
|
|
|
template<typename R>
|
|
struct get_traits<R, true> {
|
|
using function_traits = common::traits::function_traits<decltype(&R::get)>;
|
|
using result_type = common::traits::remove_optional_t<typename function_traits::return_type>;
|
|
};
|
|
|
|
// is_updatable_resource<R>
|
|
//
|
|
|
|
template<typename, typename = std::void_t<>>
|
|
struct is_updatable_resource : std::false_type {};
|
|
|
|
template<typename R>
|
|
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<decltype(&R::update)>::type
|
|
>
|
|
&&
|
|
(
|
|
// Check if return value of R::update() is void.
|
|
std::is_same_v<
|
|
void,
|
|
typename common::traits::function_traits<decltype(&R::update)>::return_type
|
|
>
|
|
||
|
|
// Check if return value of R::update() is a gettable resource.
|
|
is_gettable_resource_v<
|
|
typename common::traits::function_traits<decltype(&R::update)>::return_type
|
|
>
|
|
||
|
|
// Check if return value of R::update() is a representation.
|
|
representation::traits::is_representation_v<
|
|
typename common::traits::function_traits<decltype(&R::update)>::return_type
|
|
>
|
|
)
|
|
> {
|
|
};
|
|
|
|
template<typename R>
|
|
inline constexpr bool is_updatable_resource_v{is_updatable_resource<R>::value};
|
|
|
|
template<typename R, bool = is_updatable_resource_v<R>>
|
|
struct update_traits {
|
|
using input_representation_type = void;
|
|
using result_type = void;
|
|
};
|
|
|
|
template<typename R>
|
|
struct update_traits<R, true> {
|
|
using function_traits = common::traits::function_traits<decltype(&R::update)>;
|
|
using input_representation_type = common::traits::first_arg_t<decltype(&R::update)>;
|
|
using result_type = typename function_traits::return_type;
|
|
};
|
|
|
|
// is_creatable_resource<R>
|
|
//
|
|
|
|
template<typename, typename = std::void_t<>>
|
|
struct is_creatable_resource : std::false_type {};
|
|
|
|
template<typename R>
|
|
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<decltype(&R::create)>
|
|
>
|
|
&&
|
|
(
|
|
// Check if return value of R::create() is void.
|
|
std::is_same_v<
|
|
void,
|
|
typename common::traits::function_traits<decltype(&R::create)>::return_type
|
|
>
|
|
||
|
|
// Check if return value of R::create() is a gettable resource.
|
|
is_gettable_resource_v<
|
|
typename common::traits::function_traits<decltype(&R::create)>::return_type
|
|
>
|
|
||
|
|
// Check if return value of R::create() is a representation.
|
|
representation::traits::is_representation_v<
|
|
typename common::traits::function_traits<decltype(&R::create)>::return_type
|
|
>
|
|
)
|
|
> {
|
|
};
|
|
|
|
template<typename R>
|
|
inline constexpr bool is_creatable_resource_v{is_creatable_resource<R>::value};
|
|
|
|
template<typename R, bool = is_creatable_resource_v<R>>
|
|
struct create_traits {
|
|
using input_representation_type = void;
|
|
using result_type = void;
|
|
};
|
|
|
|
template<typename R>
|
|
struct create_traits<R, true> {
|
|
using function_traits = common::traits::function_traits<decltype(&R::create)>;
|
|
using input_representation_type = common::traits::first_arg_t<decltype(&R::create)>;
|
|
using result_type = typename function_traits::return_type;
|
|
};
|
|
|
|
// is_erasable_resource<R>
|
|
//
|
|
|
|
template<typename, typename = std::void_t<>>
|
|
struct is_erasable_resource : std::false_type {};
|
|
|
|
template<typename R>
|
|
struct is_erasable_resource<
|
|
R,
|
|
std::void_t<
|
|
decltype(std::declval<R const>().erase())
|
|
>
|
|
> : std::true_type{
|
|
};
|
|
|
|
template<typename R>
|
|
constexpr bool is_erasable_resource_v{is_erasable_resource<R>::value};
|
|
|
|
// is_resource
|
|
//
|
|
|
|
template<typename R>
|
|
struct is_resource : std::bool_constant<
|
|
is_gettable_resource_v<R> ||
|
|
is_updatable_resource_v<R> ||
|
|
is_creatable_resource_v<R> ||
|
|
is_erasable_resource_v<R>
|
|
> {
|
|
};
|
|
|
|
template<typename R>
|
|
constexpr bool is_resource_v{is_resource<R>::value};
|
|
|
|
// has_location
|
|
//
|
|
|
|
template<typename, typename = std::void_t<>>
|
|
struct has_location : std::false_type {};
|
|
|
|
template<typename R>
|
|
struct has_location<
|
|
R,
|
|
std::void_t<
|
|
decltype(
|
|
uri::uri_t{
|
|
std::declval<R const>().location()
|
|
}
|
|
)
|
|
>
|
|
> : std::true_type{
|
|
};
|
|
|
|
template<typename R>
|
|
constexpr bool has_location_v{has_location<R>::value};
|
|
|
|
// resource_traits
|
|
//
|
|
|
|
template<typename R>
|
|
struct resource_traits {
|
|
using resource_type = R;
|
|
|
|
// properties
|
|
//
|
|
|
|
static constexpr bool has_entity_tag{
|
|
representation::traits::has_entity_tag_v<resource_type>
|
|
};
|
|
|
|
static constexpr bool has_last_modified{
|
|
representation::traits::has_last_modified_v<resource_type>
|
|
};
|
|
|
|
static constexpr bool has_location{
|
|
has_location_v<resource_type>
|
|
};
|
|
|
|
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<resource_type>
|
|
};
|
|
|
|
using get_traits = traits::get_traits<resource_type>;
|
|
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<resource_type>
|
|
};
|
|
|
|
using update_traits = traits::update_traits<resource_type>;
|
|
using update_input_representation_type = typename update_traits::input_representation_type;
|
|
using update_input_representation_type_traits = representation::traits::input_representation_traits<update_input_representation_type>;
|
|
using update_result_type = typename update_traits::result_type;
|
|
|
|
// CREATE
|
|
//
|
|
static constexpr bool is_creatable{
|
|
is_creatable_resource_v<resource_type>
|
|
};
|
|
|
|
using create_traits = traits::create_traits<resource_type>;
|
|
using create_input_representation_type = typename create_traits::input_representation_type;
|
|
using create_input_representation_type_traits = representation::traits::input_representation_traits<create_input_representation_type>;
|
|
using create_result_type = typename create_traits::result_type;
|
|
|
|
// ERASE
|
|
//
|
|
static constexpr bool is_erasable{
|
|
is_erasable_resource_v<resource_type>
|
|
};
|
|
};
|
|
|
|
} // namespace code::seafire::resources::traits
|
|
|
|
#endif
|