skullc-peripherals/Messaging/Inc/messaging_parser.hpp
Erki 55a8efa579
All checks were successful
continuous-integration/drone/push Build is passing
Clang format pass
2021-04-03 17:49:25 +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