libstp
Robotics library for Botball
Loading...
Searching...
No Matches
ui_messages.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <stdexcept>
6#include <string>
7#include <vector>
8
9namespace raccoon::ui
10{
11 namespace detail
12 {
13 inline void require_available(std::size_t offset, std::size_t needed, std::size_t len)
14 {
15 if (offset > len || needed > len - offset)
16 {
17 throw std::runtime_error("screen message buffer underflow");
18 }
19 }
20
21 inline void append_u32(std::vector<std::uint8_t>& out, std::uint32_t value)
22 {
23 out.push_back(static_cast<std::uint8_t>((value >> 24) & 0xFFu));
24 out.push_back(static_cast<std::uint8_t>((value >> 16) & 0xFFu));
25 out.push_back(static_cast<std::uint8_t>((value >> 8) & 0xFFu));
26 out.push_back(static_cast<std::uint8_t>(value & 0xFFu));
27 }
28
29 inline void append_i64(std::vector<std::uint8_t>& out, std::int64_t value)
30 {
31 const auto raw = static_cast<std::uint64_t>(value);
32 for (int shift = 56; shift >= 0; shift -= 8)
33 {
34 out.push_back(static_cast<std::uint8_t>((raw >> shift) & 0xFFu));
35 }
36 }
37
38 inline std::uint32_t read_u32(const std::uint8_t* data, std::size_t len, std::size_t& offset)
39 {
40 require_available(offset, 4, len);
41 const auto value = (static_cast<std::uint32_t>(data[offset]) << 24)
42 | (static_cast<std::uint32_t>(data[offset + 1]) << 16)
43 | (static_cast<std::uint32_t>(data[offset + 2]) << 8)
44 | static_cast<std::uint32_t>(data[offset + 3]);
45 offset += 4;
46 return value;
47 }
48
49 inline std::int64_t read_i64(const std::uint8_t* data, std::size_t len, std::size_t& offset)
50 {
51 require_available(offset, 8, len);
52 std::uint64_t raw = 0;
53 for (int i = 0; i < 8; ++i)
54 {
55 raw = (raw << 8) | static_cast<std::uint64_t>(data[offset + i]);
56 }
57 offset += 8;
58 return static_cast<std::int64_t>(raw);
59 }
60
61 inline void append_string(std::vector<std::uint8_t>& out, const std::string& value)
62 {
63 if (value.size() > 0xFFFFFFFFu)
64 {
65 throw std::runtime_error("screen message string too large");
66 }
67 append_u32(out, static_cast<std::uint32_t>(value.size()));
68 out.insert(out.end(), value.begin(), value.end());
69 }
70
71 inline std::string read_string(
72 const std::uint8_t* data, std::size_t len, std::size_t& offset)
73 {
74 const auto size = read_u32(data, len, offset);
75 require_available(offset, size, len);
76 std::string value(
77 reinterpret_cast<const char*>(data + offset),
78 reinterpret_cast<const char*>(data + offset + size));
79 offset += size;
80 return value;
81 }
82 }
83
85 {
86 std::int64_t timestamp{};
87 std::string screen_name{};
88 std::string entries{};
89
90 void encode(std::vector<std::uint8_t>& out) const
91 {
95 }
96
97 static ScreenRender decode(const std::uint8_t* data, std::size_t len)
98 {
99 std::size_t offset = 0;
100 ScreenRender msg;
101 msg.timestamp = detail::read_i64(data, len, offset);
102 msg.screen_name = detail::read_string(data, len, offset);
103 msg.entries = detail::read_string(data, len, offset);
104 if (offset != len)
105 {
106 throw std::runtime_error("trailing bytes after ScreenRender payload");
107 }
108 return msg;
109 }
110 };
111
113 {
114 std::int64_t timestamp{};
115 std::string screen_name{};
116 std::string value{};
117 std::string reason{};
118
119 void encode(std::vector<std::uint8_t>& out) const
120 {
125 }
126
127 static ScreenRenderAnswer decode(const std::uint8_t* data, std::size_t len)
128 {
129 std::size_t offset = 0;
131 msg.timestamp = detail::read_i64(data, len, offset);
132 msg.screen_name = detail::read_string(data, len, offset);
133 msg.value = detail::read_string(data, len, offset);
134 msg.reason = detail::read_string(data, len, offset);
135 if (offset != len)
136 {
137 throw std::runtime_error("trailing bytes after ScreenRenderAnswer payload");
138 }
139 return msg;
140 }
141 };
142}
void append_string(std::vector< std::uint8_t > &out, const std::string &value)
std::int64_t read_i64(const std::uint8_t *data, std::size_t len, std::size_t &offset)
std::uint32_t read_u32(const std::uint8_t *data, std::size_t len, std::size_t &offset)
void append_u32(std::vector< std::uint8_t > &out, std::uint32_t value)
void require_available(std::size_t offset, std::size_t needed, std::size_t len)
std::string read_string(const std::uint8_t *data, std::size_t len, std::size_t &offset)
void append_i64(std::vector< std::uint8_t > &out, std::int64_t value)
void encode(std::vector< std::uint8_t > &out) const
static ScreenRenderAnswer decode(const std::uint8_t *data, std::size_t len)
void encode(std::vector< std::uint8_t > &out) const
static ScreenRender decode(const std::uint8_t *data, std::size_t len)