ADC/net/adc_netmessage.h
2024-05-25 20:58:15 +03:00

231 lines
6.7 KiB
C++

#pragma once
#include <ranges>
#include "../common/adc_traits.h"
#include "../common/adc_utils.h"
/*
ABSTRACT DEVICE COMPONENTS LIBRARY
*/
/* GENERIC NETWORK MESSAGE CLASS */
namespace adc
{
namespace traits
{
// from message view to byte converter concept
template <typename T, typename BT, typename VT>
concept adc_to_bytes_func_c = std::invocable<T, const VT&> && !std::convertible_to<traits::adc_retval_t<T>, BT>;
// from bytes to message view converter concept
template <typename T, typename BT, typename VT>
concept adc_from_bytes_func_c = std::invocable<T, const BT&> && std::convertible_to<traits::adc_retval_t<T>, VT>;
struct AdcTheSameTypeTag {
};
} // namespace traits
template <std::ranges::output_range<char> ByteStorageT,
std::ranges::output_range<std::reference_wrapper<const ByteStorageT>> StorageSeqT>
class AdcNetMessageInterface
{
protected:
ByteStorageT _byteStorage;
StorageSeqT _storageSequence;
AdcNetMessageInterface() = default;
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
AdcNetMessageInterface(const T& v, const Ts&... vs) : AdcNetMessageInterface()
{
appendBytes(v, vs...);
}
virtual ~AdcNetMessageInterface() = default;
AdcNetMessageInterface(const AdcNetMessageInterface&) = default;
AdcNetMessageInterface(AdcNetMessageInterface&&) = default;
AdcNetMessageInterface& operator=(const AdcNetMessageInterface&) = default;
AdcNetMessageInterface& operator=(AdcNetMessageInterface&&) = default;
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
void appendBytes(const T& v, const Ts&... vs)
{
if constexpr (std::is_array_v<std::remove_cvref_t<T>>) {
appendBytes(std::string_view(v), vs...);
} else {
std::ranges::copy(v, std::back_inserter(_byteStorage));
}
if constexpr (sizeof...(Ts)) {
appendBytes(vs...);
}
}
template <traits::adc_input_char_range T, traits::adc_input_char_range... Ts>
void setBytes(const T& v, const Ts&... vs)
{
_byteStorage = ByteStorageT();
appendBytes(v, vs...);
}
template <std::input_iterator IterT>
void setBytes(IterT begin, IterT end)
{
_byteStorage = ByteStorageT(begin, end);
}
template <std::input_iterator IterT>
void appendBytes(IterT begin, IterT end)
{
std::copy(begin, end, std::back_inserter(_byteStorage));
}
public:
typedef ByteStorageT byte_storage_t;
typedef StorageSeqT storage_seq_t;
virtual size_t byteSize()
{
auto v = _storageSequence |
std::views::transform([](const auto& el) -> const ByteStorageT& { return el.get(); }) |
std::views::join;
return std::ranges::distance(v.begin(), v.end());
}
virtual ByteStorageT bytes()
{
auto v = _storageSequence |
std::views::transform([](const auto& el) -> const ByteStorageT& { return el.get(); }) |
std::views::join;
return ByteStorageT{v.begin(), v.end()};
};
virtual const StorageSeqT& storageSeq() = 0;
};
template <std::ranges::output_range<char> ByteStorageT = std::vector<char>,
typename MessageViewT = traits::AdcTheSameTypeTag>
class AdcGenericNetMessage
: public AdcNetMessageInterface<ByteStorageT, std::array<std::reference_wrapper<const ByteStorageT>, 1>>
{
using base_t = AdcNetMessageInterface<ByteStorageT, std::array<std::reference_wrapper<const ByteStorageT>, 1>>;
public:
using typename base_t::byte_storage_t;
using typename base_t::storage_seq_t;
using message_view_t =
std::conditional_t<std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>, ByteStorageT, MessageViewT>;
AdcGenericNetMessage() = default;
template <std::convertible_to<MessageViewT> T,
traits::adc_to_bytes_func_c<ByteStorageT, MessageViewT> CONVT =
decltype(utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)>
AdcGenericNetMessage(T&& v, CONVT&& conv_func = utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)
: AdcGenericNetMessage()
{
setMessage(std::forward<T>(v), std::forward<CONVT>(conv_func));
}
virtual ~AdcGenericNetMessage() = default;
template <std::convertible_to<MessageViewT> T,
traits::adc_to_bytes_func_c<ByteStorageT, message_view_t> CONVT =
decltype(utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)>
void setMessage(T&& v, CONVT&& conv_func = utils::AdcDefaultValueConverter<>::serialize<ByteStorageT, T>)
{
if constexpr (std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
this->setBytes(std::forward<T>(v));
} else {
_messageView(std::forward<T>(v));
this->_byteStorage = std::forward<CONVT>(conv_func)(_messageView);
}
}
message_view_t messageView() const
{
if constexpr (std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
return this->_byteStorage;
} else {
return _messageView;
}
}
const storage_seq_t& storageSeq() override
{
this->_storageSequence[0] = this->_byteStorage;
return this->_storageSequence;
};
// factory function
template <traits::adc_input_char_range BT,
traits::adc_from_bytes_func_c<ByteStorageT, message_view_t> CONVT =
decltype(utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)>
static AdcGenericNetMessage fromBytes(
BT&& bytes,
CONVT&& conv_func = utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)
{
AdcGenericNetMessage msg;
msg.setBytes(std::forward<BT>(bytes));
if constexpr (!std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
msg._messageView = conv_func(msg._byteStorage);
}
return msg;
}
template <std::input_iterator IterT,
traits::adc_from_bytes_func_c<ByteStorageT, message_view_t> CONVT =
decltype(utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)>
static AdcGenericNetMessage fromBytes(
IterT begin,
IterT end,
CONVT&& conv_func = utils::AdcDefaultValueConverter<>::deserialize<message_view_t, ByteStorageT>)
{
AdcGenericNetMessage msg;
msg.setBytes(begin, end);
if constexpr (!std::is_same_v<MessageViewT, traits::AdcTheSameTypeTag>) {
msg._messageView = conv_func(msg._byteStorage);
}
return msg;
}
protected:
MessageViewT _messageView;
};
} // namespace adc