This commit is contained in:
Timur A. Fatkhullin
2025-10-22 23:52:14 +03:00
parent 42a4349c76
commit 80ec2382ea
5 changed files with 266 additions and 35 deletions

View File

@@ -156,7 +156,7 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FI
// arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT)
// precision must be given as non-negative integer number
// e.g.
// "COORDPREC 2 1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
// "COORDPREC 2,1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
//
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
@@ -492,23 +492,25 @@ static_assert(mcc_netmsg_valid_keys_c<MccNetMessageValidKeywords>, "");
template <typename T>
concept mcc_netmessage_c = requires(T t) { T(); };
/* helper types to format serialized celestial coordinates */
/* it can be used as inputs in "construct" method or corresponded constructor */
// format of output (serialized) coordinates
enum class MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM };
// precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds)
struct MccNetMessageCoordPrec {
uint8_t hour_prec = 2;
uint8_t deg_prec = 1;
};
template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
mcc_netmsg_valid_keys_c BASE_T = MccNetMessageValidKeywords>
class MccNetMessage
{
public:
/* helper types to format serialized celestial coordinates */
/* it can be used as inputs in "construct" method or corresponded constructor */
// format of output (serialized) coordinates
enum MccNetMessageCoordFormat { CFMT_DEGREES, CFMT_SGM };
// precision of sexagesimal coordinates (number of decimal places in seconds/arcseconds)
struct MccNetMessageCoordPrec {
uint8_t hour_prec = 2;
uint8_t deg_prec = 1;
};
protected:
class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer
{
@@ -599,6 +601,46 @@ protected:
pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{});
mcc_copy_celestial_point(pt, &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);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordFormat>) {
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 = MccNetMessageCoordFormat::CFMT_SGM;
} else if (v.compare(MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR) == 0) {
value = MccNetMessageCoordFormat::CFMT_DEGREES;
} else {
return std::make_error_code(std::errc::invalid_argument);
}
} else if constexpr (std::same_as<VT, MccNetMessageCoordPrec>) {
std::vector<int64_t> v;
auto ec = (*this)(std::forward<IR>(bytes), v);
if (ec) {
return ec;
}
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);
}
@@ -610,7 +652,7 @@ protected:
class DefaultSerializer
{
MccNetMessageCoordFormat _currentCoordFormat = MccNetMessage::CFMT_SGM;
MccNetMessageCoordFormat _currentCoordFormat = MccNetMessageCoordFormat::CFMT_SGM;
MccNetMessageCoordPrec _currentCoordPrec{2, 1};
public:
@@ -635,12 +677,12 @@ protected:
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 (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_celestial_point_c<T>) {
if (_currentCoordFormat == MccNetMessage::CFMT_DEGREES) {
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 {
@@ -683,7 +725,6 @@ protected:
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::same_as<T, MccNetMessage>) {
} else if constexpr (std::formattable<T, char>) {
std::format_to(std::back_inserter(bytes), "{}", value);
} else {
@@ -751,8 +792,13 @@ public:
}
size_t paramSize() const
{
return _params.size();
}
template <std::ranges::range R>
R params(size_t start_idx, size_t Nelemes = std::numeric_limits<size_t>::max())
R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max())
requires(traits::mcc_view_or_output_char_range<R> || traits::mcc_range_of_char_range<R>)
{
if (start_idx >= _params.size()) {
@@ -791,7 +837,7 @@ public:
}
}
std::string_view params(size_t start_idx, size_t Nelemes = std::numeric_limits<size_t>::max())
std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max())
{
return params<std::string_view>(start_idx, Nelemes);
}