Untitled
unknown
plain_text
9 months ago
3.9 kB
17
Indexable
#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <optional>
#include <span>
#include <string>
#include <variant>
#include <vector>
#include <type_traits>
#if __cplusplus >= 202002L
template <typename T>
using TypeTag = std::type_identity<T>;
#else
template <typename T>
struct TypeTag
{
using type = T;
};
#endif
namespace mock {
namespace constants {
enum class FirmwareCommand {
IDENTITY = 0,
STATE_PUSH = 1,
COMMAND_COUNT //Please ensure this definition is always at the end.
};
} // namespace constants
namespace types {
struct IdentityInfo
{
std::string name;
int version;
};
struct Telemetry
{
float temperature;
float voltage;
};
} // namespace types
using data_t = std::span<const std::byte>;
namespace helper {
template<typename T>
std::optional<T> deserialize_payload(data_t data);
template<>
std::optional<types::IdentityInfo> deserialize_payload<types::IdentityInfo>(data_t)
{
return types::IdentityInfo{"DeviceZ", 16};
}
template<>
std::optional<types::Telemetry> deserialize_payload<types::Telemetry>(data_t)
{
return types::Telemetry{36.5f, 3.3f};
}
} // namespace helper
class EventBus {
public:
void publish(const types::IdentityInfo& info) const
{
std::cout << "[EventBus] Published IdentityInfo: name = " << info.name << ", version = " << info.version
<< "\n";
}
void publish(const types::Telemetry& telemetry) const
{
std::cout << "[EventBus] Published Telemetry: temperature = " << telemetry.temperature
<< ", voltage = " << telemetry.voltage << "\n";
}
};
class Processor {
public:
void process_payload(constants::FirmwareCommand cmd_id, data_t payload) const
{
using payload_variant_t =
std::variant<TypeTag<types::IdentityInfo>, TypeTag<types::Telemetry>>;
static constexpr std::array<
payload_variant_t,
static_cast<std::size_t>(constants::FirmwareCommand::COMMAND_COUNT)>
payload_struct_array{{
TypeTag<types::IdentityInfo>{},
TypeTag<types::Telemetry>{}
// another commands and payload types
}};
const size_t index = static_cast<std::size_t>(cmd_id);
if (index >= payload_struct_array.size())
{
std::cout << "[Processor] Unknown command.\n";
return;
}
const auto& tag{payload_struct_array[index]};
std::visit(
[&bus = m_eventbus, payload]<typename T>(T) {
using tag_type_t = typename T::type;
const auto res{helper::deserialize_payload<tag_type_t>(payload)};
if (!res.has_value()) [[unlikely]]
{
std::cout << "deserialize error\n";
return;
}
// if u need check special type
/*
if constexpr (std::is_same_v<types::IdentityInfo, tag_type_t>)
{
// bla bla bla
}
*/
bus.publish(res.value());
},
tag);
}
private:
EventBus m_eventbus;
};
} // namespace mock
int main()
{
using namespace mock;
Processor processor{};
std::vector<std::byte> fake_payload{std::byte{0x01}, std::byte{0x02}, std::byte{0x03}};
std::cout << ">>> Processing IDENTITY...\n";
processor.process_payload(constants::FirmwareCommand::IDENTITY, fake_payload);
std::cout << "\n>>> Processing STATE_PUSH...\n";
processor.process_payload(constants::FirmwareCommand::STATE_PUSH, fake_payload);
std::cout << "\n>>> Processing UNKNOWN COMMAND...\n";
processor.process_payload(static_cast<constants::FirmwareCommand>(999), fake_payload);
return EXIT_SUCCESS;
}Editor is loading...
Leave a Comment