118 lines
3.4 KiB
C++
118 lines
3.4 KiB
C++
#pragma once
|
|
|
|
|
|
/*
|
|
|
|
ABSTRACT DEVICE COMPONENTS LIBRARY
|
|
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include "../common/adc_value_holder.h"
|
|
|
|
/*
|
|
|
|
*/
|
|
|
|
namespace adc
|
|
{
|
|
|
|
template <typename IdentT, typename SerializedT = std::string>
|
|
class AdcDeviceCommand
|
|
{
|
|
protected:
|
|
IdentT _ident;
|
|
|
|
std::unique_ptr<AdcValueHolder> _commandArgUptr;
|
|
|
|
std::function<void()> _execFuncWrapper;
|
|
std::function<void(std::any&)> _deserializerWrapper;
|
|
|
|
public:
|
|
typedef IdentT ident_t;
|
|
typedef SerializedT serialized_t;
|
|
|
|
|
|
template <typename ExecFuncT,
|
|
typename DeserializerT,
|
|
typename ValidatorT = decltype(AdcValueHolder::AdcValueHolderDummyValidator)>
|
|
AdcDeviceCommand(const IdentT& ident,
|
|
ExecFuncT&& exec_func,
|
|
DeserializerT&& deserializer,
|
|
ValidatorT&& validator = AdcValueHolder::AdcValueHolderDummyValidator)
|
|
: _ident(ident), _commandArgUptr()
|
|
{
|
|
using sign_t = traits::adc_func_traits<ExecFuncT>;
|
|
|
|
static_assert(std::tuple_size_v<typename sign_t::args_t> > 1,
|
|
"COMMAND EXECUTION FUNCTION MUST ACCEPT 0 OR EXACTLY 1 ARGUMENT!!!");
|
|
|
|
if constexpr (std::tuple_size_v<typename sign_t::args_t>) { // command with argument
|
|
using value_t = typename sign_t::arg1_t;
|
|
|
|
static_assert(std::predicate<ValidatorT, const value_t&>, "INVALID TYPE OF VALIDATOR");
|
|
|
|
static_assert(std::invocable<DeserializerT, const SerializedT&>, "INVALID TYPE OF DESERIALIZER");
|
|
static_assert(std::is_convertible_v<std::invoke_result_t<DeserializerT, const SerializedT&>, value_t>,
|
|
"INVALID RETURN TYPE OF DESERIALIZER");
|
|
|
|
|
|
auto command_arg = std::shared_ptr<value_t>(value_t());
|
|
|
|
_commandArgUptr = std::make_unique<AdcValueHolder>(
|
|
[command_arg]() { return *command_arg; }, [command_arg](const value_t& value) { *command_arg = value; },
|
|
std::forward<ValidatorT>(validator));
|
|
|
|
_execFuncWrapper = [wrapper = traits::adc_pf_wrapper(std::forward<ExecFuncT>(exec_func)), this]() {
|
|
auto& exec_func = std::get<0>(wrapper);
|
|
value_t val = std::any_cast<value_t>(*_commandArgUptr);
|
|
exec_func(val);
|
|
};
|
|
|
|
|
|
_deserializerWrapper =
|
|
[wrapper = traits::adc_pf_wrapper(std::forward<DeserializerT>(deserializer))](std::any& val) {
|
|
auto& deserializer = std::get<0>(wrapper);
|
|
val = std::make_any<value_t>(deserializer(std::any_cast<SerializedT>(val)));
|
|
};
|
|
|
|
// setup only convert-to-native-value function (deserializer)
|
|
_commandArgUptr->addConvertFunc<SerializedT>(std::forward<DeserializerT>(deserializer), []() {});
|
|
} else { // command without argument (ignore deserializer and validator)
|
|
_execFuncWrapper = std::forward<ExecFuncT>(exec_func);
|
|
}
|
|
}
|
|
|
|
|
|
virtual ~AdcDeviceCommand() = default;
|
|
|
|
|
|
/* PUBLIC METHODS */
|
|
|
|
IdentT ident() const { return ident; }
|
|
|
|
|
|
template <typename ValueT>
|
|
void operator()(const ValueT& value)
|
|
{
|
|
if (_commandArgUptr) { // command with argument
|
|
*_commandArgUptr = value;
|
|
}
|
|
_execFuncWrapper();
|
|
}
|
|
|
|
|
|
void operator()()
|
|
{
|
|
if (_commandArgUptr) { // command with argument
|
|
throw 1;
|
|
}
|
|
|
|
_execFuncWrapper();
|
|
}
|
|
};
|
|
|
|
|
|
} // namespace adc
|