This commit is contained in:
2025-10-28 18:01:22 +03:00
parent 85dfa2e9a5
commit 78e4bb182c
10 changed files with 277 additions and 200 deletions

View File

@@ -516,90 +516,22 @@ protected:
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)
{
if constexpr (mcc_celestial_point_c<VT>) {
std::vector<std::string> vs;
auto ec = base_t::operator()(std::forward<IR>(bytes), vs);
if (ec) {
return ec;
}
if (vs.size() < 2) { // at least a pair of coordinates must be given
return std::make_error_code(std::errc::invalid_argument);
}
MccCelestialPoint pt{.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
if (vs.size() > 2) { // pair of coordinates and the pair kind
pt.pair_kind = MccCoordStrToPairKind(vs[2]);
if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_GENERIC) {
return std::make_error_code(std::errc::invalid_argument);
}
}
if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
// J2000.0: 11:58:55.816 1 January 2000 UTC
auto tp = std::chrono::sys_days(std::chrono::year_month_day(
std::chrono::January / std::chrono::day(1) / std::chrono::year(2000))) +
std::chrono::hours(11) + std::chrono::minutes(58) + std::chrono::milliseconds(55816);
mcc_tp2tp(tp, pt.time_point);
} else {
if (vs.size() > 3) { // coordinates epoch is given
// std::chrono::sys_time<std::chrono::system_clock::duration> tp;
// std::istringstream iss(std::string{utils::trimSpaces(vs[3])});
// std::chrono::from_stream(iss, "%FT%T", tp);
// if (iss.fail()) {
// return std::make_error_code(std::errc::invalid_argument);
// }
// mcc_tp2tp(tp, pt.time_point);
MccCelestialCoordEpoch cep;
// bool ok = cep.fromCharRange(utils::trimSpaces(vs[3]));
bool ok = cep.fromCharRange(vs[3]);
if (!ok) {
return std::make_error_code(std::errc::invalid_argument);
}
mcc_tp2tp(cep.UTC(), pt.time_point);
} else { // no time point - use NOW
mcc_tp2tp(std::chrono::system_clock::now(), pt.time_point);
}
}
std::optional<double> ang1, ang2;
switch (pt.pair_kind) {
// if sexagesimal then hours:minutes:seconds form
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
case mcc::MccCoordPairKind::COORDS_KIND_RADEC_APP:
case mcc::MccCoordPairKind::COORDS_KIND_HADEC_APP:
ang1 = mcc::utils::parsAngleString(vs[0], true);
break;
default:
// if sexagesimal then degrees:arcminutes:arcseconds form
ang1 = mcc::utils::parsAngleString(vs[0]);
}
if (!ang1) {
return std::make_error_code(std::errc::invalid_argument);
}
ang2 = mcc::utils::parsAngleString(vs[1]);
if (!ang2) {
return std::make_error_code(std::errc::invalid_argument);
}
pt.X = MccAngle(ang1.value(), mcc::MccDegreeTag{});
pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{});
mcc_copy_celestial_point(pt, &value);
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) {
@@ -651,20 +583,12 @@ protected:
class DefaultSerializer
{
MccNetMessageCoordFormat _currentCoordFormat = MccNetMessageCoordFormat::CFMT_SGM;
MccNetMessageCoordPrec _currentCoordPrec{2, 1};
friend class MccNetMessage;
MccCoordinateSerializer::SerializedCoordFormat _coordFmt{};
MccCoordinateSerializer::SexagesimalCoordPrec _coordPrec{};
public:
void setCoordFormat(MccNetMessageCoordFormat fmt)
{
_currentCoordFormat = fmt;
}
void setCoordPrec(MccNetMessageCoordPrec prec)
{
_currentCoordPrec = prec;
}
template <typename T, traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
@@ -680,83 +604,30 @@ protected:
// 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>) {
// output format: RA, DEC, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point
// in the case of sexagesimal output X,Y coordinates will be interpretated
// according to value.pair_kind field
if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) {
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
MccAngle(value.RA).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.DEC).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.HA).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.AZ).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.ZD).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.ALT).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.X).degrees(), MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.Y).degrees());
} else {
std::format_to(std::back_inserter(bytes), "{}{}{}{}{}{}{}{}{}{}{}{}",
MccAngle(value.RA).sexagesimal(true, _currentCoordPrec.hour_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.DEC).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.HA).sexagesimal(true, _currentCoordPrec.hour_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.AZ).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.ZD).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ,
MccAngle(value.ALT).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
static MccEqtHrzCoordsSerializer sr;
// interpretate X,Y angles according to .pair_kind field
switch (value.pair_kind) {
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
std::format_to(std::back_inserter(bytes), "{}{}{}{}",
MccAngle(value.X).sexagesimal(true, _currentCoordPrec.hour_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
break;
default:
std::format_to(std::back_inserter(bytes), "{}{}",
MccAngle(value.X).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
}
std::format_to(std::back_inserter(bytes), "{}",
MccAngle(value.Y).sexagesimal(false, _currentCoordPrec.deg_prec));
}
std::format_to(std::back_inserter(bytes), "{0:}{1:}{2:}{3:%F}T{3:%T}",
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccCoordPairKindToStr(value.pair_kind),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.time_point);
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
sr.setFormat(_coordFmt);
sr.setPrecision(_coordPrec);
sr(value, bytes);
} else if constexpr (mcc_celestial_point_c<T>) {
if (_currentCoordFormat == MccNetMessageCoordFormat::CFMT_DEGREES) {
std::format_to(std::back_inserter(bytes), "{}{}{}", MccAngle(value.X).degrees(),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccAngle(value.Y).degrees());
} else {
switch (value.pair_kind) {
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
std::format_to(std::back_inserter(bytes), "{}{}",
MccAngle(value.X).sexagesimal(true, _currentCoordPrec.hour_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
break;
default:
std::format_to(std::back_inserter(bytes), "{}{}",
MccAngle(value.X).sexagesimal(false, _currentCoordPrec.deg_prec),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
}
MccCelestialPointSerializer sr;
std::format_to(std::back_inserter(bytes), "{}",
MccAngle(value.Y).sexagesimal(false, _currentCoordPrec.deg_prec));
}
sr.setDelimiter(MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ);
sr.setFormat(_coordFmt);
sr.setPrecision(_coordPrec);
std::format_to(std::back_inserter(bytes), "{0:}{1:}{2:}{3:%F}T{3:%T}",
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, MccCoordPairKindToStr(value.pair_kind),
MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ, value.time_point);
sr(value, bytes);
} else if constexpr (std::ranges::range<T>) {
auto sz = std::ranges::size(value);
if (sz == 0) {
@@ -796,7 +667,7 @@ public:
MccNetMessage(KT&& key, PTs&&... params)
requires traits::mcc_output_char_range<BYTEREPR_T>
{
construct(std::forward<KT>(key), std::forward<PTs>(params)...);
construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
}
template <traits::mcc_input_char_range R>
@@ -964,9 +835,22 @@ public:
template <traits::mcc_input_char_range KT, typename... PTs>
std::error_code construct(KT&& key, PTs&&... params)
requires traits::mcc_output_char_range<BYTEREPR_T>
{
return construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
}
//
// serializing function SerFuncT - a callable with the signature:
// template<typename T, mcc_output_char_range R>
// void ser_func(const T& val, R&& buffer)
//
template <typename SerFuncT, traits::mcc_input_char_range KT, typename... PTs>
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
requires(traits::mcc_output_char_range<BYTEREPR_T> &&
!traits::mcc_input_char_range<std::remove_cvref_t<SerFuncT>>)
{
if constexpr (std::is_pointer_v<std::decay_t<KT>>) {
return construct(std::string_view(key), std::forward<PTs>(params)...);
return construct(std::forward<SerFuncT>(ser_func), std::string_view(key), std::forward<PTs>(params)...);
}
@@ -993,7 +877,7 @@ public:
if constexpr (sizeof...(PTs)) {
std::ranges::copy(MCC_COMMPROTO_KEYPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
convertFunc(par_idx, std::forward<PTs>(params)...);
convertFunc(std::forward<SerFuncT>(ser_func), par_idx, std::forward<PTs>(params)...);
for (size_t i = 0; i < par_idx.size(); i += 2) {
_params.emplace_back(_msgBuffer.begin() + par_idx[i], _msgBuffer.begin() + par_idx[i + 1]);
@@ -1005,7 +889,6 @@ public:
return {};
}
template <traits::mcc_input_char_range R>
constexpr MccNetMessageError fromCharRange(const R& r)
{
@@ -1072,30 +955,68 @@ protected:
template <typename T, typename... Ts>
void convertFunc(std::vector<size_t>& idx, const T& par, const Ts&... pars)
{
if constexpr (std::same_as<T, MccNetMessageCoordFormat>) {
_defaultSerializer.setCoordFormat(par);
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, MccNetMessageCoordPrec>) {
_defaultSerializer.setCoordPrec(par);
} 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...);
// }
}
};
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;
} 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));
}
}
} else {
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
_defaultSerializer(par, _msgBuffer);
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));
convertFunc(idx, pars...);
}
}
};
if constexpr (sizeof...(Ts)) {
convertFunc(std::forward<SerFuncT>(ser_func), idx, pars...);
}
}
};
static_assert(MccNetMessage<std::string, MccNetMessageValidKeywords>{"ACK"}.withKey("ACK"));