#pragma once /* ABSTRACT DEVICE COMPONENTS LIBRARY */ #include "../common/adc_value.h" namespace adc { // error codes enum class AdcDeviceAttributeErrorCode : int { ERROR_OK, ERROR_READ_ONLY, ERROR_WRITE_ONLY }; } // namespace adc namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace adc { // error category struct AdcDeviceAttributeErrorCategory : public std::error_category { AdcDeviceAttributeErrorCategory() : std::error_category() {} const char* name() const noexcept { return "ADC_DEVICE_ATTRIBUTE_CATEGORY"; } std::string message(int ec) const { AdcDeviceAttributeErrorCode err = static_cast(ec); switch (err) { case AdcDeviceAttributeErrorCode::ERROR_OK: return "OK"; case AdcDeviceAttributeErrorCode::ERROR_READ_ONLY: return "device attribute is read-only"; case AdcDeviceAttributeErrorCode::ERROR_WRITE_ONLY: return "device attribute is write-only"; default: return "UNKNOWN"; } } static const AdcDeviceAttributeErrorCategory& get() { static const AdcDeviceAttributeErrorCategory constInst; return constInst; } }; inline std::error_code make_error_code(AdcDeviceAttributeErrorCode ec) { return std::error_code(static_cast(ec), AdcDeviceAttributeErrorCategory::get()); } template class AdcDeviceAttribute : protected AdcSerializingValueHolder { typedef AdcSerializingValueHolder base_t; template using ret_value_t = base_t::template ret_value_t; public: typedef IdentT ident_t; typedef SerializedT serialized_t; enum AccessType { ReadOnly, WriteOnly, ReadWrite }; template constexpr static T DummyGetter() { return T(); } template constexpr static void DummySetter(const T&) { } template constexpr static SerializedT DummySerializer(const T&) { return SerializedT(); } template constexpr static T DummyDeserializer(const SerializedT&) { return T(); } /* CONSTRUCTORS AND DESTRUCTOR */ // general read-write attribute constructor template AdcDeviceAttribute(const IdentT& ident, SerValHolderTs&&... ctor_args) : base_t(std::forward(ctor_args)...), _ident(ident), _accessType(ReadWrite) { } // read-only attribute constructor template , typename SRT = decltype(utils::AdcDefaultValueConverter<>::serialize)> AdcDeviceAttribute(const IdentT& ident, GT&& getter, SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize) requires std::invocable && std::invocable : AdcDeviceAttribute(ident, std::forward(getter), AdcDeviceAttribute::DummySetter, AdcValueHolder::AdcValueHolderDummyValidator, std::forward(serializer), AdcDeviceAttribute::DummyDeserializer) { _accessType = ReadOnly; } template , typename SRT = decltype(utils::AdcDefaultValueConverter<>::serialize)> AdcDeviceAttribute(const IdentT& ident, traits::adc_tuple_like<> auto&& tpl, GT&& getter, SRT&& serializer = utils::AdcDefaultValueConverter<>::serialize) requires std::invocable && std::invocable : AdcDeviceAttribute(ident, std::forward(tpl), std::forward(getter), AdcDeviceAttribute::DummySetter, AdcValueHolder::AdcValueHolderDummyValidator, std::forward(serializer), AdcDeviceAttribute::DummyDeserializer) { _accessType = ReadOnly; } // write-only attribute constructor template >, typename DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize)> AdcDeviceAttribute(const IdentT& ident, ST&& setter, std::predicate auto&& validator, DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize) requires std::invocable : AdcDeviceAttribute(ident, AdcDeviceAttribute::DummyGetter, std::forward(setter), std::forward(validator), AdcDeviceAttribute::DummySerializer, std::forward(deserializer)) { _accessType = WriteOnly; } template >, typename DSRT = decltype(utils::AdcDefaultValueConverter<>::deserialize)> AdcDeviceAttribute(const IdentT& ident, traits::adc_tuple_like<> auto&& tpl, ST&& setter, std::predicate auto&& validator, DSRT&& deserializer = utils::AdcDefaultValueConverter<>::deserialize) requires std::invocable : AdcDeviceAttribute(ident, std::forward(tpl), AdcDeviceAttribute::DummyGetter, std::forward(setter), std::forward(validator), AdcDeviceAttribute::DummySerializer, std::forward(deserializer)) { _accessType = WriteOnly; } AdcDeviceAttribute(const AdcDeviceAttribute&) = default; AdcDeviceAttribute(AdcDeviceAttribute&&) = default; virtual ~AdcDeviceAttribute() = default; IdentT ident() const { return _ident; } AccessType accessType() const { return _accessType; } template operator UT() const { if (_accessType == WriteOnly) { throw std::system_error(AdcDeviceAttributeErrorCode::ERROR_WRITE_ONLY); } return base_t::operator UT(); } AdcDeviceAttribute& operator=(const AdcDeviceAttribute&) = default; AdcDeviceAttribute& operator=(AdcDeviceAttribute&&) = default; template AdcDeviceAttribute& operator=(UT&& value) { if (_accessType == ReadOnly) { throw std::system_error(AdcDeviceAttributeErrorCode::ERROR_READ_ONLY); } base_t::operator=(std::forward(value)); return *this; } protected: IdentT _ident; AccessType _accessType; }; } // namespace adc