This commit is contained in:
2026-02-11 12:07:27 +03:00
parent b1df84a87f
commit 652fbd0890
6 changed files with 191 additions and 266 deletions

View File

@@ -8,10 +8,11 @@
#include <algorithm>
#include <string_view>
#include "mcc_angle.h"
#include "mcc_defaults.h"
#include "mcc_generics.h"
#include "mcc_utils.h"
#include "mcc_serializer.h"
#include "mcc_deserializer.h"
namespace mcc::network
{
@@ -60,57 +61,6 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR = "RE
/* BELOW IS ONE OF THE PROTOCOL OPTIONS CORRESPONDING MCC_GENERIC_MOUNT_C CONCEPT */
/* predefined parameters */
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC_ICRS = "RADEC_ICRS"; // ICRS RA and DEC
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC = "RADEC"; // apparent RA and DEC
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_HADEC = "HADEC"; // apparent HA and DEC
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZZD = "AZZD"; // azimuth and zenithal distance
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZALT = "AZALT"; // azimuth and altitude
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_XY = "XY"; // hardware (encoder) coordinates
// static constexpr MccCoordPairKind mcc_str2pairkind(std::string_view spair)
// {
// return spair == MCC_COMMPROTO_COORD_KIND_RADEC_ICRS ? MccCoordPairKind::COORDS_KIND_RADEC_ICRS
// : spair == MCC_COMMPROTO_COORD_KIND_RADEC ? MccCoordPairKind::COORDS_KIND_RADEC_APP
// : spair == MCC_COMMPROTO_COORD_KIND_HADEC ? MccCoordPairKind::COORDS_KIND_HADEC_APP
// : spair == MCC_COMMPROTO_COORD_KIND_AZZD ? MccCoordPairKind::COORDS_KIND_AZZD
// : spair == MCC_COMMPROTO_COORD_KIND_AZALT ? MccCoordPairKind::COORDS_KIND_AZALT
// : spair == MCC_COMMPROTO_COORD_KIND_XY ? MccCoordPairKind::COORDS_KIND_XY
// : MccCoordPairKind::COORDS_KIND_GENERIC;
// }
template <mcc::traits::mcc_char_range R>
static constexpr MccCoordPairKind mcc_str2pairkind(R&& spair)
{
if constexpr (std::is_pointer_v<std::decay_t<R>>) {
return mcc_str2pairkind(std::string_view{spair});
}
const auto hash = mcc::utils::FNV1aHash(std::forward<R>(spair));
return hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_RADEC_ICRS) ? MccCoordPairKind::COORDS_KIND_RADEC_ICRS
: hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_RADEC) ? MccCoordPairKind::COORDS_KIND_RADEC_APP
: hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_HADEC) ? MccCoordPairKind::COORDS_KIND_HADEC_APP
: hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_AZZD) ? MccCoordPairKind::COORDS_KIND_AZZD
: hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_AZALT) ? MccCoordPairKind::COORDS_KIND_AZALT
: hash == mcc::utils::FNV1aHash(MCC_COMMPROTO_COORD_KIND_XY) ? MccCoordPairKind::COORDS_KIND_XY
: MccCoordPairKind::COORDS_KIND_GENERIC;
}
static constexpr std::string_view mcc_pairkind2str(MccCoordPairKind kind)
{
return kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS ? MCC_COMMPROTO_COORD_KIND_RADEC_ICRS
: kind == MccCoordPairKind::COORDS_KIND_RADEC_APP ? MCC_COMMPROTO_COORD_KIND_RADEC
: kind == MccCoordPairKind::COORDS_KIND_HADEC_APP ? MCC_COMMPROTO_COORD_KIND_HADEC
: kind == MccCoordPairKind::COORDS_KIND_AZZD ? MCC_COMMPROTO_COORD_KIND_AZZD
: kind == MccCoordPairKind::COORDS_KIND_AZALT ? MCC_COMMPROTO_COORD_KIND_AZALT
: kind == MccCoordPairKind::COORDS_KIND_XY ? MCC_COMMPROTO_COORD_KIND_XY
: "UNKNOWN";
}
/* keywords */
@@ -301,149 +251,14 @@ template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
class MccNetMessage
{
protected:
class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer
// just a wrapper class to hold MccSerializer<T> specializations
struct DefaultSerializer
{
protected:
using base_t = mcc::utils::MccSimpleDeserializer;
inline static mcc::MccCelestialPointDeserializer _cpDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
inline static mcc::MccEqtHrzCoordsDeserializer _eqhrDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
inline static mcc::MccTelemetryDataDeserializer _telemetryDeserializer{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ};
public:
DefaultDeserializer() : base_t(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ) {}
template <traits::mcc_input_char_range IR, typename VT>
std::error_code operator()(IR&& bytes, VT& value) const
template <traits::mcc_output_char_range OR, typename T>
auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const
{
if constexpr (mcc_telemetry_data_c<VT>) {
return _telemetryDeserializer(std::forward<IR>(bytes), value);
} else if constexpr (mcc_eqt_hrz_coord_c<VT>) {
return _eqhrDeserializer(std::forward<IR>(bytes), value);
} else if constexpr (mcc_celestial_point_c<VT>) {
return _cpDeserializer(std::forward<IR>(bytes), value);
} else if constexpr (std::same_as<VT, MccCoordPairKind>) {
value = MccCoordStrToPairKind(bytes);
if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
// return std::make_error_code(std::errc::invalid_argument);
return MccCoordinateConvErrorCode::ERROR_INVALID_CPAIR;
}
} else if constexpr (std::same_as<VT, MccCoordinateSerializer::SerializedCoordFormat>) {
std::string v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
return ec;
}
if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR) == 0) {
value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_SGM;
} else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) {
value = MccCoordinateSerializer::SerializedCoordFormat::CFMT_DEGREES;
} else {
// return std::make_error_code(std::errc::invalid_argument);
return MccCoordinateConvErrorCode::ERROR_INVALID_COORD_FMT;
}
} else if constexpr (std::same_as<VT, MccCoordinateSerializer::SexagesimalCoordPrec>) {
std::vector<int64_t> v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
// return ec;
return MccCoordinateConvErrorCode::ERROR_INVALID_COORD_PREC;
}
auto hprec = v[0];
value.hour_prec = hprec > 0 ? (hprec < std::numeric_limits<decltype(value.hour_prec)>::max()
? hprec
: std::numeric_limits<decltype(value.hour_prec)>::max())
: 2;
if (v.size() == 1) {
value.deg_prec = 1;
} else {
auto dprec = v[1];
value.deg_prec = dprec > 0 ? dprec < std::numeric_limits<decltype(value.deg_prec)>::max()
? dprec
: std::numeric_limits<decltype(value.deg_prec)>::max()
: 1;
}
} else {
return base_t::operator()(std::forward<IR>(bytes), value);
}
return {};
}
};
class DefaultSerializer
{
friend class MccNetMessage;
MccCoordinateSerializer::SerializedCoordFormat _coordFmt{};
MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{};
public:
template <typename T, traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
if constexpr (std::is_arithmetic_v<T>) {
std::format_to(std::back_inserter(bytes), "{}", value);
} else if constexpr (std::convertible_to<T, std::string>) {
std::ranges::copy(static_cast<std::string>(value), std::back_inserter(bytes));
} else if constexpr (std::constructible_from<std::string, T>) {
std::ranges::copy(std::string(value), std::back_inserter(bytes));
} else if constexpr (traits::mcc_char_range<T>) {
std::ranges::copy(std::string(value.begin(), value.end()), std::back_inserter(bytes));
// } else if constexpr (std::same_as<T, MccCoordPairKind>) {
// std::ranges::copy(mcc_pairkind2str(value), std::back_inserter(bytes));
} else if constexpr (traits::mcc_time_duration_c<T>) {
(*this)(value.count(), bytes);
} else if constexpr (mcc_telemetry_data_c<T>) {
static MccTelemetryDataSerializer sr;
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
sr.setFormat(_coordFmt);
sr.setPrecision(_coordPrec);
sr(value, bytes);
} else if constexpr (mcc_eqt_hrz_coord_c<T>) {
static MccEqtHrzCoordsSerializer sr;
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
sr.setFormat(_coordFmt);
sr.setPrecision(_coordPrec);
sr(value, bytes);
} else if constexpr (mcc_celestial_point_c<T>) {
static MccCelestialPointSerializer sr;
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
sr.setFormat(_coordFmt);
sr.setPrecision(_coordPrec);
sr(value, bytes);
} else if constexpr (std::ranges::range<T>) {
auto sz = std::ranges::size(value);
if (sz == 0) {
return;
}
(*this)(*value.begin(), bytes); // the first element
if (sz > 1) {
for (auto const& el : value | std::views::drop(1)) {
std::ranges::copy(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, std::back_inserter(bytes));
(*this)(el, bytes);
}
}
} else if constexpr (std::same_as<T, std::error_code>) {
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}", value.value(),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.message(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
value.category().name());
} else if constexpr (std::formattable<T, char>) {
std::format_to(std::back_inserter(bytes), "{}", value);
} else {
static_assert(false, "UNSUPPORTED TYPE!!!");
}
return impl::MccSerializer<T>{}(bytes, value, pars);
}
};
@@ -588,13 +403,15 @@ public:
template <typename T, typename DeserFuncT>
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const
{
static_assert(std::invocable<DeserFuncT, typename decltype(_params)::value_type const&, T&, impl::mcc_serialization_params_t const&>, "INVALID DESERIALIZTION FUNCTION!");
if (idx >= _params.size()) {
return std::unexpected{std::make_error_code(std::errc::value_too_large)};
}
T val;
auto ec = std::forward<DeserFuncT>(deser_func)(_params[idx], val);
auto ec = std::forward<DeserFuncT>(deser_func)(_params[idx], val, _serializationParams);
if (ec) {
return std::unexpected(ec);
} else {
@@ -605,7 +422,7 @@ public:
template <typename T>
std::expected<T, std::error_code> paramValue(size_t idx) const
{
return paramValue<T>(idx, _defaultDeserializer);
return paramValue<T>(idx, impl::MccDeserializer<T>{}); // use one of specialization of MccDeserializer templated class
}
@@ -637,7 +454,7 @@ public:
//
// serializing function SerFuncT - a callable with the signature:
// template<typename T, mcc_output_char_range R>
// void ser_func(const T& val, R&& buffer)
// void ser_func(R&& buffer, const T& val, mcc_serialization_params_t const& pars)
//
template <typename SerFuncT, traits::mcc_input_char_range KT, typename... PTs>
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
@@ -743,69 +560,30 @@ protected:
BYTEREPR_T _msgBuffer{};
inline static DefaultDeserializer _defaultDeserializer{};
DefaultSerializer _defaultSerializer{};
template <typename T, typename... Ts>
void convertFunc(std::vector<size_t>& idx, const T& par, const Ts&... pars)
{
if constexpr (std::same_as<T, MccCoordinateSerializer::SerializedCoordFormat>) {
_defaultSerializer._coordFmt = par;
if constexpr (sizeof...(Ts)) {
convertFunc(idx, pars...);
}
} else if constexpr (std::same_as<T, MccCoordinateSerializer::SexagesimalCoordPrec>) {
_defaultSerializer._coordPrec = par;
if constexpr (sizeof...(Ts)) {
convertFunc(idx, pars...);
}
} else {
convertFunc(_defaultSerializer, idx, par, pars...);
// idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
// _defaultSerializer(par, _msgBuffer);
// idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
// if constexpr (sizeof...(Ts)) {
// std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
// convertFunc(idx, pars...);
// }
}
};
impl::mcc_serialization_params_t _serializationParams{.seq_delim{MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ}, .elem_delim{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ}};
template <typename SerFuncT, typename T, typename... Ts>
void convertFunc(SerFuncT&& ser_func, std::vector<size_t>& idx, const T& par, const Ts&... pars)
requires(!std::same_as<std::remove_cvref_t<SerFuncT>, std::vector<size_t>>)
{
if constexpr (std::derived_from<std::remove_cvref_t<SerFuncT>, DefaultSerializer>) {
if constexpr (std::same_as<T, MccCoordinateSerializer::SerializedCoordFormat>) {
// _defaultSerializer._coordFmt = par;
ser_func._coordFmt = par;
} else if constexpr (std::same_as<T, MccCoordinateSerializer::SexagesimalCoordPrec>) {
_defaultSerializer._coordPrec = par;
} else {
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
std::forward<SerFuncT>(ser_func)(par, _msgBuffer);
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
if constexpr (sizeof...(Ts)) {
std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
}
}
if constexpr (std::same_as<T, MccSerializedCoordPairFormat>) {
_serializationParams.coordpair_format = par;
} else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) {
_serializationParams.angle_prec = par;
} else {
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
std::forward<SerFuncT>(ser_func)(par, _msgBuffer);
// convertFunc(std::forward<SerFuncT>(ser_func), idx, par);
std::forward<SerFuncT>(ser_func)(_msgBuffer, par, _serializationParams);
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
if constexpr (sizeof...(Ts)) {
std::ranges::copy(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
std::ranges::copy(_serializationParams.seq_delim, std::back_inserter(_msgBuffer));
}
}