skullc-peripherals/Messaging/Inc/messaging_parser.hpp
Erki 60bad24319
Some checks failed
continuous-integration/drone/push Build is failing
The great renaming, part 1
2021-06-08 23:18:56 +03:00

128 lines
2.3 KiB
C++

//
// Created by erki on 27.03.21.
//
#ifndef SKULLC_MESSAGING_PARSER_HPP_
#define SKULLC_MESSAGING_PARSER_HPP_
#include <array>
#include <cstdint>
#include <cstring>
namespace Messaging
{
template<typename P, typename std::size_t N>
class Parser
{
public:
using Packet = P;
const std::size_t buffer_length = N;
Parser() { reset(); }
Parser(const Parser&) = delete;
Parser(Parser&&) = delete;
void reset()
{
state_ = State_::Preamble;
expected_ = sizeof(P::preamble);
current_pos_ = 0;
current_offset_ = 0;
}
void pushByte(const std::uint8_t byte)
{
if (packetReady())
return;
const std::uint32_t buffer_loc = current_offset_ + current_pos_;
switch (state_)
{
case State_::Preamble:
if (byte != P::preamble[current_pos_])
{
reset();
return;
}
[[fallthrough]];
case State_::Length:
case State_::Body:
buffer_[buffer_loc] = byte;
current_pos_++;
break;
default:
break;
}
if (current_pos_ == expected_)
{
setupNextState_();
}
}
bool packetReady() const { return state_ == State_::Done; }
bool getPacket(Packet& packet) const
{
return packet.deserialize(buffer_.data(), current_offset_);
}
private:
enum class State_ : std::uint32_t
{
Preamble,
Length,
Body,
Done
};
std::array<std::uint8_t, N> buffer_;
State_ state_ = State_::Preamble;
std::uint32_t current_pos_ = 0;
std::uint32_t current_offset_ = 0;
std::uint32_t expected_ = 0;
template<typename T>
T deserializeLength_(const std::uint32_t offset)
{
std::uint8_t* begin = buffer_.data() + offset;
T len(0);
std::memcpy(&len, begin, sizeof(T));
return len;
}
void setupNextState_()
{
switch (state_)
{
case State_::Preamble:
state_ = State_::Length;
expected_ = sizeof(typename P::length_type);
break;
case State_::Length:
state_ = State_::Body;
expected_ = deserializeLength_<typename P::length_type>(current_offset_);
break;
case State_::Body:
state_ = State_::Done;
break;
default:
break;
}
current_offset_ += current_pos_;
current_pos_ = 0;
}
};
}// namespace Messaging
#endif// SKULLC_MESSAGING_PARSER_HPP_