diff --git a/mcc_deser.h b/mcc_deser.h new file mode 100644 index 0000000..de7ffd4 --- /dev/null +++ b/mcc_deser.h @@ -0,0 +1,301 @@ +#pragma once + +#include + +#include "mcc_epoch.h" +#include "mcc_serialization_common.h" + +namespace mcc::impl +{ + +enum class MccDeserializerErrorCode : int { + ERROR_OK, + ERROR_UNDERLYING_DESERIALIZER, + ERROR_INVALID_SERIALIZED_VALUE, + ERROR_COORD_TRANSFORM +}; + +} // namespace mcc::impl + + + +namespace std +{ + +template <> +class is_error_code_enum : public true_type +{ +}; + +} // namespace std + + +namespace mcc::impl +{ + + +// error category +struct MccDeserializerCategory : public std::error_category { + MccDeserializerCategory() : std::error_category() {} + + const char* name() const noexcept + { + return "MCC-DESERIALIZER-ERR-CATEGORY"; + } + + std::string message(int ec) const + { + MccDeserializerErrorCode err = static_cast(ec); + + switch (err) { + case MccDeserializerErrorCode::ERROR_OK: + return "OK"; + case MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER: + return "error returned by underlying deserializer"; + case MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE: + return "invalid serialized value"; + case MccDeserializerErrorCode::ERROR_COORD_TRANSFORM: + return "coordinates transformation error"; + default: + return "UNKNOWN"; + } + } + + static const MccDeserializerCategory& get() + { + static const MccDeserializerCategory constInst; + return constInst; + } +}; + + +inline std::error_code make_error_code(MccDeserializerErrorCode ec) +{ + return std::error_code(static_cast(ec), MccDeserializerCategory::get()); +} + + + +/* BASE DESERIALIZER CLASS (FOR IMPLEMENTATIONS BELOW) */ + +struct MccDeserializerBase : mcc_deserializer_interface_t { + using typename mcc_deserializer_interface_t::error_t; + + virtual ~MccDeserializerBase() = default; + + +protected: + MccDeserializerBase() = default; + + // + // empty == true, if the 'input' is empty or if all elements consist of only spaces + // + static std::vector splitValueIntoElements(traits::mcc_input_char_range auto const& input, + mcc_serialization_params_c auto const& params, + bool& empty) + { + static_assert(std::ranges::contiguous_range, "NOT IMPLEMENTED FOR NON-CONTIGUIUS RANGES!!!"); + + std::vector res; + + if (std::ranges::size(input)) { + empty = true; + + std::ranges::for_each(std::views::split(input, params.elem_delim), [&res, &empty](auto const& el) { + std::back_inserter(res) = utils::trimSpaces(std::string_view{el.begin(), el.end()}); + if (empty && res.back().size()) { + empty = false; + } + }); + } else { + empty = true; + } + + return res; + } + + template R, typename... DeserParamsT> + static error_t deserializingRange(mcc_deserializer_c auto& dsr, + traits::mcc_input_char_range auto const& input, + R& r, + mcc_serialization_params_c auto const& params) + { + if (std::ranges::size(input) == 0) { // ignore an empty input, just return empty range?!! + r = R{}; + return MccDeserializerErrorCode::ERROR_OK; + } + + auto r_str = std::views::split(input, params.seq_delim); + VT val; + + auto it = r.begin(); + for (auto const& el : r_str) { + auto err = dsr(el, val, std::forward(params)...); + if (err) { + return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER); + } + + if (it == r.end()) { + std::back_inserter(r) = val; + it = r.end(); + } else { + *it = val; + ++it; + } + } + + return MccDeserializerErrorCode::ERROR_OK; + } +}; + + +/* MAIN (FALLBACK) TEMPLATED IMPLEMENTATION */ + + +template +struct MccDeserializer : MccDeserializerBase { + static constexpr std::string_view deserializerName{"MCC-FALLBACK-DESERIALIZER"}; + + virtual ~MccDeserializer() = default; + + + template + error_t operator()(traits::mcc_input_char_range auto const& input, + VT& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + if constexpr (std::is_arithmetic_v) { + auto v = mcc::utils::numFromStr(utils::trimSpaces(input)); + if (!v.has_value()) { + return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; + } + + value = v.value(); + } else if constexpr (mcc::traits::mcc_output_char_range) { + VT r; + if constexpr (traits::mcc_array_c) { + size_t N = + std::ranges::size(r) <= std::ranges::size(input) ? std::ranges::size(r) : std::ranges::size(input); + + for (size_t i = 0; i < N; ++i) { + r[i] = input[i]; + } + if (std::ranges::size(r) > N) { + for (size_t i = N; i < std::ranges::size(r); ++i) { + r[i] = '\0'; + } + } + } else { + std::ranges::copy(input, std::back_inserter(r)); + } + + value = r; + } else if constexpr (std::ranges::range) { + using el_t = std::ranges::range_value_t; + + static_assert(std::ranges::output_range, "INVALID RANGE TYPE!!!"); + + // no reference or constants allowed + static_assert(std::is_reference_v || std::is_const_v, "INVALID RANGE ELEMENT TYPE!!!"); + + MccDeserializer dsr; + return deserializingRange(dsr, input, value, params); + } else if constexpr (traits::mcc_time_duration_c) { + typename VT::rep vd; + + MccDeserializer dsr; + + auto err = dsr(trimSpaces(input), vd, params); + if (err) { + return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER); + } + + value = VT{vd}; + } else { + static_assert(false, "UNSUPPORTED VALUE TYPE!!!"); + } + + + return MccDeserializerErrorCode::ERROR_OK; + } +}; + + +/* SPECIALIZATION FOR THE SOME CONCEPTS */ + +template +struct MccDeserializer : MccDeserializerBase { + static constexpr std::string_view deserializerName{"MCC-COORD-EPOCH-DESERIALIZER"}; + + template + error_t operator()(traits::mcc_input_char_range auto const& input, + VT& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + bool ok = value.fromCharRange(input); + if (!ok) { + return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; + } + + return MccDeserializerErrorCode::ERROR_OK; + } +}; + + + +template + requires(!std::is_arithmetic_v && mcc_angle_c) +struct MccDeserializer : MccDeserializerBase { + static constexpr std::string_view deserializerName{"MCC-ANGLE-DESERIALIZER"}; + + template + error_t operator()(traits::mcc_input_char_range auto const& input, + VT& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + bool hms = params.angle_format == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS; + + auto res = utils::parsAngleString(input, hms); + if (res) { // returned angle is in degrees!!! + value = res.value() * MCC_DEGRESS_TO_RADS; + } else { + return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; + } + + return MccDeserializerErrorCode::ERROR_OK; + } +}; + + +template +struct MccDeserializer : MccDeserializerBase { + static constexpr std::string_view deserializerName{"MCC-SKYPOINT-DESERIALIZER"}; + + template + error_t operator()(traits::mcc_input_char_range auto const& input, + VT& value, + ParamsT const& params = mcc_serialization_params_t{}) + { + // valid format: XY[TIME-POINTPAIR-KIND] + // XY (assumed RADEC_ICRS and J2000.0 epoch) + + bool empty; + + auto elems = MccDeserializerBase::splitValueIntoElements(input, params, empty); + + if (empty || (elems.size() < 2) || (elems.size() == 3)) { + return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE; + } + + MccCoordPairKind pair_kind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS}; + MccCelestialCoordEpoch epoch; // J2000.0 + + MccAngle x, y; + MccDeserializer dsr_ang; + + typename MccDeserializer::error_t dsr_err; + } +}; + + +} // namespace mcc::impl diff --git a/mcc_ser.h b/mcc_ser.h index a381d4e..8a1df2e 100644 --- a/mcc_ser.h +++ b/mcc_ser.h @@ -158,7 +158,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-FALLBACK-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -207,7 +207,7 @@ struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-SYSTIME-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -224,7 +224,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-ANGLE-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -270,7 +270,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-COORD-EPOCH-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -312,7 +312,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-COORD-PAIR-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -367,7 +367,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-SKYPOINT-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -434,7 +434,7 @@ template struct MccSerializer : MccSerializerBase { constexpr static std::string_view serializerName{"MCC-TELEMETRY-DATA-SERIALIZER"}; - template + template error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = mcc_serialization_params_t{}) @@ -687,4 +687,7 @@ struct MccSerializer : MccSerializerBase { } }; + +static_assert(mcc_serializer_c>, "!!!"); + } // namespace mcc::impl diff --git a/mcc_serialization_common.h b/mcc_serialization_common.h index 334a254..29da0f5 100644 --- a/mcc_serialization_common.h +++ b/mcc_serialization_common.h @@ -352,14 +352,14 @@ protected: -struct MccDeserializerBase : mcc_deserializer_interface_t { - virtual ~MccDeserializerBase() = default; +// struct MccDeserializerBase : mcc_deserializer_interface_t { +// virtual ~MccDeserializerBase() = default; - using typename mcc_deserializer_interface_t::error_t; +// using typename mcc_deserializer_interface_t::error_t; -protected: - MccDeserializerBase() = default; -}; +// protected: +// MccDeserializerBase() = default; +// }; // template // struct MccSerializerBase : mcc_serializer_interface_t, details::_params_manipulator_t {