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