...
This commit is contained in:
@@ -259,6 +259,9 @@ if(BUILD_TESTS)
|
|||||||
|
|
||||||
add_executable(mcc_pzone_test tests/mcc_pzone_test.cpp)
|
add_executable(mcc_pzone_test tests/mcc_pzone_test.cpp)
|
||||||
target_link_libraries(mcc_pzone_test PRIVATE ${PROJECT_NAME})
|
target_link_libraries(mcc_pzone_test PRIVATE ${PROJECT_NAME})
|
||||||
|
|
||||||
|
add_executable(mcc_netmsg_test tests/mcc_netmsg_test.cpp)
|
||||||
|
target_link_libraries(mcc_netmsg_test PRIVATE ${PROJECT_NAME})
|
||||||
else()
|
else()
|
||||||
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
||||||
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ static constexpr double MCC_TWO_PI = std::numbers::pi * 2.0;
|
|||||||
static constexpr double MCC_SIDERAL_TO_UT1_RATIO = 1.002737909350795; // sideral/UT1
|
static constexpr double MCC_SIDERAL_TO_UT1_RATIO = 1.002737909350795; // sideral/UT1
|
||||||
|
|
||||||
static constexpr double MCC_J2000_MJD = 51544.5;
|
static constexpr double MCC_J2000_MJD = 51544.5;
|
||||||
|
static constexpr double MCC_MJD_ZERO = 2400000.5;
|
||||||
|
|
||||||
|
|
||||||
// a value to represent of infinite time duration according to type of duration representation
|
// a value to represent of infinite time duration according to type of duration representation
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ struct MccDeserializer : MccDeserializerBase {
|
|||||||
static_assert(std::ranges::output_range<VT, el_t>, "INVALID RANGE TYPE!!!");
|
static_assert(std::ranges::output_range<VT, el_t>, "INVALID RANGE TYPE!!!");
|
||||||
|
|
||||||
// no reference or constants allowed
|
// no reference or constants allowed
|
||||||
static_assert(std::is_reference_v<el_t> || std::is_const_v<el_t>, "INVALID RANGE ELEMENT TYPE!!!");
|
static_assert(!(std::is_reference_v<el_t> || std::is_const_v<el_t>), "INVALID RANGE ELEMENT TYPE!!!");
|
||||||
|
|
||||||
MccDeserializer<el_t> dsr;
|
MccDeserializer<el_t> dsr;
|
||||||
return deserializingRange<el_t>(dsr, input, value, params);
|
return deserializingRange<el_t>(dsr, input, value, params);
|
||||||
@@ -206,7 +206,7 @@ struct MccDeserializer : MccDeserializerBase {
|
|||||||
|
|
||||||
MccDeserializer<typename VT::rep> dsr;
|
MccDeserializer<typename VT::rep> dsr;
|
||||||
|
|
||||||
auto err = dsr(trimSpaces(input), vd, params);
|
auto err = dsr(utils::trimSpaces(input), vd, params);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
}
|
}
|
||||||
@@ -370,4 +370,59 @@ struct MccDeserializer<VT> : MccDeserializerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
MccSerializedAngleFormatPrec& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
// valid format: hour_prec[<params.elem_delim>deg_prec<params.elem_delim>decimals]
|
||||||
|
|
||||||
|
std::vector<uint8_t> v;
|
||||||
|
|
||||||
|
auto err = MccDeserializer<decltype(v)>{}(input, v);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 0) {
|
||||||
|
value.hour_prec = v[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 1) {
|
||||||
|
value.deg_prec = v[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 2) {
|
||||||
|
value.decimals = v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccDeserializer<MccSerializedCoordPairFormat> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-COORD-PAIR-FORMAT-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
MccSerializedCoordPairFormat& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
value = MccSerializedCoordPairFormatStrToValue(input);
|
||||||
|
|
||||||
|
if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN){
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include "mcc_angle.h"
|
|
||||||
#include "mcc_defaults.h"
|
|
||||||
#include "mcc_generics.h"
|
|
||||||
#include "mcc_utils.h"
|
#include "mcc_utils.h"
|
||||||
|
#include "mcc_serializer.h"
|
||||||
|
#include "mcc_deserializer.h"
|
||||||
|
|
||||||
namespace mcc::network
|
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 */
|
/* 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 */
|
/* keywords */
|
||||||
|
|
||||||
@@ -301,149 +251,14 @@ template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
|
|||||||
class MccNetMessage
|
class MccNetMessage
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
class DefaultDeserializer : protected mcc::utils::MccSimpleDeserializer
|
|
||||||
|
// just a wrapper class to hold MccSerializer<T> specializations
|
||||||
|
struct DefaultSerializer
|
||||||
{
|
{
|
||||||
protected:
|
template <traits::mcc_output_char_range OR, typename T>
|
||||||
using base_t = mcc::utils::MccSimpleDeserializer;
|
auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if constexpr (mcc_telemetry_data_c<VT>) {
|
return impl::MccSerializer<T>{}(bytes, value, pars);
|
||||||
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!!!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -588,13 +403,15 @@ public:
|
|||||||
template <typename T, typename DeserFuncT>
|
template <typename T, typename DeserFuncT>
|
||||||
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const
|
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()) {
|
if (idx >= _params.size()) {
|
||||||
return std::unexpected{std::make_error_code(std::errc::value_too_large)};
|
return std::unexpected{std::make_error_code(std::errc::value_too_large)};
|
||||||
}
|
}
|
||||||
|
|
||||||
T val;
|
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) {
|
if (ec) {
|
||||||
return std::unexpected(ec);
|
return std::unexpected(ec);
|
||||||
} else {
|
} else {
|
||||||
@@ -605,7 +422,7 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
std::expected<T, std::error_code> paramValue(size_t idx) const
|
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:
|
// serializing function SerFuncT - a callable with the signature:
|
||||||
// template<typename T, mcc_output_char_range R>
|
// 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>
|
template <typename SerFuncT, traits::mcc_input_char_range KT, typename... PTs>
|
||||||
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
|
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
|
||||||
@@ -743,69 +560,30 @@ protected:
|
|||||||
|
|
||||||
BYTEREPR_T _msgBuffer{};
|
BYTEREPR_T _msgBuffer{};
|
||||||
|
|
||||||
inline static DefaultDeserializer _defaultDeserializer{};
|
|
||||||
|
|
||||||
DefaultSerializer _defaultSerializer{};
|
DefaultSerializer _defaultSerializer{};
|
||||||
|
|
||||||
template <typename T, typename... Ts>
|
impl::mcc_serialization_params_t _serializationParams{.seq_delim{MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ}, .elem_delim{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ}};
|
||||||
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...);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename SerFuncT, typename T, typename... Ts>
|
template <typename SerFuncT, typename T, typename... Ts>
|
||||||
void convertFunc(SerFuncT&& ser_func, std::vector<size_t>& idx, const T& par, const Ts&... pars)
|
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>>)
|
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>) {
|
if constexpr (std::same_as<T, MccSerializedCoordPairFormat>) {
|
||||||
// _defaultSerializer._coordFmt = par;
|
_serializationParams.coordpair_format = par;
|
||||||
ser_func._coordFmt = par;
|
} else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) {
|
||||||
} else if constexpr (std::same_as<T, MccCoordinateSerializer::SexagesimalCoordPrec>) {
|
_serializationParams.angle_prec = par;
|
||||||
_defaultSerializer._coordPrec = par;
|
|
||||||
} else {
|
} else {
|
||||||
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
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()));
|
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||||
|
|
||||||
if constexpr (sizeof...(Ts)) {
|
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));
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,8 @@ protected:
|
|||||||
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
}
|
}
|
||||||
if (++i < N) {
|
if (++i < N) {
|
||||||
MccSerializerBase::addSeqDelimiter(output, params);
|
// MccSerializerBase::addSeqDelimiter(output, params);
|
||||||
|
MccSerializerBase::addElemDelimiter(output, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,31 +164,26 @@ struct MccSerializer : MccSerializerBase {
|
|||||||
VT const& value,
|
VT const& value,
|
||||||
ParamsT const& params = mcc_serialization_params_t{})
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
{
|
{
|
||||||
if constexpr (std::formattable<VT, char>) {
|
if constexpr (std::convertible_to<VT, std::string>) {
|
||||||
std::format_to(std::back_inserter(output), "{}", value);
|
std::string s = value;
|
||||||
} else if constexpr (std::convertible_to<VT, std::string>) {
|
std::ranges::copy(s, std::back_inserter(output));
|
||||||
auto err = MccSerializer<std::string>{}(output, static_cast<std::string>(value), params);
|
// auto err = MccSerializer<std::string>{}(output, static_cast<std::string>(value), params);
|
||||||
if (err) {
|
// if (err) {
|
||||||
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
// return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
}
|
// }
|
||||||
} else if constexpr (std::ranges::range<VT>) {
|
} else if constexpr (std::ranges::range<VT>) {
|
||||||
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
|
||||||
// special range (character sequence)
|
// special range (character sequence)
|
||||||
if constexpr (std::same_as<value_t, char>) {
|
if constexpr (std::same_as<value_t, char>) {
|
||||||
std::string str;
|
std::ranges::copy(value, std::back_inserter(output));
|
||||||
std::ranges::copy(value, std::back_inserter(str));
|
|
||||||
|
|
||||||
auto err = MccSerializer<std::string>{}(output, str, params);
|
|
||||||
if (err) {
|
|
||||||
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
MccSerializer<value_t> sr;
|
MccSerializer<value_t> sr;
|
||||||
|
|
||||||
return MccSerializerBase::serializeRange<value_t>(sr, value, output, params);
|
return MccSerializerBase::serializeRange<value_t>(sr, value, output, params);
|
||||||
}
|
}
|
||||||
|
} else if constexpr (std::formattable<VT, char>) {
|
||||||
|
std::format_to(std::back_inserter(output), "{}", value);
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "UNSUPPORTED TYPE!!!");
|
static_assert(false, "UNSUPPORTED TYPE!!!");
|
||||||
}
|
}
|
||||||
@@ -199,10 +195,29 @@ struct MccSerializer : MccSerializerBase {
|
|||||||
|
|
||||||
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::mcc_time_duration_c VT>
|
||||||
|
struct MccSerializer<VT> : MccSerializerBase {
|
||||||
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
constexpr static std::string_view serializerName{"MCC-TIME-DURATION-SERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output,
|
||||||
|
VT const& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
std::format_to(std::back_inserter(output), "{}", value.count());
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* std::chrono::sys_time variants and its sequence */
|
/* std::chrono::sys_time variants and its sequence */
|
||||||
|
|
||||||
template <typename VT>
|
template <traits::mcc_systime_c VT>
|
||||||
requires traits::mcc_systime_c<VT>
|
|
||||||
struct MccSerializer<VT> : MccSerializerBase {
|
struct MccSerializer<VT> : MccSerializerBase {
|
||||||
virtual ~MccSerializer() = default;
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
|||||||
73
tests/mcc_netmsg_test.cpp
Normal file
73
tests/mcc_netmsg_test.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include <print>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <mcc_netserver_proto.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using msg1_t = mcc::network::MccNetMessage<std::string_view>;
|
||||||
|
using msg2_t = mcc::network::MccNetMessage<std::string>;
|
||||||
|
|
||||||
|
mcc::network::MccNetMessage msg3("ACK");
|
||||||
|
|
||||||
|
std::string_view sv{"TARGET 11:22:33.212; -0.23876984; RADEC "};
|
||||||
|
std::vector<char> arr{sv.begin(), sv.end()};
|
||||||
|
|
||||||
|
msg1_t msg1;
|
||||||
|
|
||||||
|
msg1.fromCharRange(arr);
|
||||||
|
|
||||||
|
std::println("msg.key = <{}>", msg1.keyword());
|
||||||
|
std::println("msg.par[1] = <{}>", msg1.param(1));
|
||||||
|
|
||||||
|
std::vector<double> vd{1.1, 2.2, 3.3};
|
||||||
|
msg2_t msg2("ACK", 12.43298042, "EEE", std::chrono::seconds(10), vd);
|
||||||
|
// msg2_t msg2("ACK");
|
||||||
|
|
||||||
|
std::println("msg.bytes = <{}>",msg2.byteRepr());
|
||||||
|
std::println("msg.key = <{}>", msg2.keyword());
|
||||||
|
std::println("msg.par[1] = <{}>", msg2.param(1));
|
||||||
|
std::println("msg.par[2] = <{}>", msg2.param(2));
|
||||||
|
|
||||||
|
|
||||||
|
auto p2 = msg2.paramValue<std::chrono::seconds>(2);
|
||||||
|
std::println("msg.parvalue[2] = <{}>", p2.value_or(std::chrono::seconds{}));
|
||||||
|
|
||||||
|
|
||||||
|
std::print("msg.parvalue[3] = <");
|
||||||
|
auto p3 = msg2.paramValue<decltype(vd)>(3);
|
||||||
|
if (p3.has_value()) {
|
||||||
|
for (auto const& el : p3.value()) {
|
||||||
|
std::print("{} ", el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::println(">");
|
||||||
|
|
||||||
|
|
||||||
|
std::println("msg.par[1-2] joined = <{}>", msg2.params(1, 2));
|
||||||
|
|
||||||
|
auto vv = msg2.params<std::list<std::string_view>>(1, 3);
|
||||||
|
std::print("msg.par[1-3] array = <");
|
||||||
|
for (auto const& el : vv) {
|
||||||
|
std::print("{} ", el);
|
||||||
|
}
|
||||||
|
std::println(">");
|
||||||
|
|
||||||
|
|
||||||
|
std::println("\n\n");
|
||||||
|
|
||||||
|
mcc::impl::MccSkyPoint spt(mcc::impl::MccSkyRADEC_APP{"10:00:00.0"_hms, 12.098687_degs});
|
||||||
|
|
||||||
|
msg2.construct("ACK", "MOUNT", spt);
|
||||||
|
std::println("msg2.bytes = <{}>", msg2.byteRepr());
|
||||||
|
|
||||||
|
auto spt_d = msg2.paramValue<mcc::impl::MccSkyPoint>(1);
|
||||||
|
|
||||||
|
if (spt_d){
|
||||||
|
std::println("msg2.parvalue(1).epoch() = {}", spt_d->epoch().MJD()+mcc::MCC_MJD_ZERO);
|
||||||
|
} else {
|
||||||
|
std::println("cannot deserialize MccSkyPoint value!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user