PhotonVision C++ v2027.0.0-alpha-2
Loading...
Searching...
No Matches
Packet.h
Go to the documentation of this file.
1/*
2 * Copyright (C) Photon Vision.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include <concepts>
21#include <cstdint>
22#include <optional>
23#include <span>
24#include <string_view>
25#include <vector>
26
27#include <wpi/util/struct/Struct.hpp>
28
29namespace photon {
30
31class Packet;
32
33// Struct is where all our actual ser/de methods are implemented
34template <typename T>
35struct SerdeType {};
36
37template <typename T>
38concept PhotonStructSerializable = requires(Packet& packet, const T& value) {
39 typename SerdeType<typename std::remove_cvref_t<T>>;
40
41 // MD6sum of the message definition
42 {
43 SerdeType<typename std::remove_cvref_t<T>>::GetSchemaHash()
44 } -> std::convertible_to<std::string_view>;
45 // JSON-encoded message chema
46 {
47 SerdeType<typename std::remove_cvref_t<T>>::GetSchema()
48 } -> std::convertible_to<std::string_view>;
49 // Unpack myself from a packet
50 {
51 SerdeType<typename std::remove_cvref_t<T>>::Unpack(packet)
52 } -> std::same_as<typename std::remove_cvref_t<T>>;
53 // Pack myself into a packet
54 {
55 SerdeType<typename std::remove_cvref_t<T>>::Pack(packet, value)
56 } -> std::same_as<void>;
57};
58
59/**
60 * A packet that holds byte-packed data to be sent over NetworkTables.
61 */
62class Packet {
63 public:
64 /**
65 * Constructs an empty packet.
66 */
67 explicit Packet(int initialCapacity = 0) : packetData(initialCapacity) {}
68
69 /**
70 * Constructs a packet with the given data.
71 * @param data The packet data.
72 */
73 explicit Packet(std::vector<uint8_t> data);
74
75 /**
76 * Clears the packet and resets the read and write positions.
77 */
78 void Clear();
79
80 /**
81 * Returns the packet data.
82 * @return The packet data.
83 */
84 inline const std::vector<uint8_t>& GetData() { return packetData; }
85
86 /**
87 * Returns the number of bytes in the data.
88 * @return The number of bytes in the data.
89 */
90 inline size_t GetDataSize() const { return packetData.size(); }
91
92 template <typename T, typename... I>
93 requires wpi::util::StructSerializable<T, I...>
94 inline void Pack(const T& value) {
95 // as WPI struct stuff assumes constant data length - reserve at least
96 // enough new space for our new member
97 size_t newWritePos = writePos + wpi::util::GetStructSize<T, I...>();
98 packetData.resize(newWritePos);
99
100 wpi::util::PackStruct(
101 std::span<uint8_t>{packetData.begin() + writePos, packetData.end()},
102 value);
103
104 writePos = newWritePos;
105 }
106
107 template <typename T>
109 inline void Pack(const T& value) {
111 }
112
113 template <typename T, typename... I>
114 requires wpi::util::StructSerializable<T, I...>
115 inline T Unpack() {
116 // Unpack this member, starting at readPos
117 T ret = wpi::util::UnpackStruct<T, I...>(
118 std::span<uint8_t>{packetData.begin() + readPos, packetData.end()});
119 readPos += wpi::util::GetStructSize<T, I...>();
120 return ret;
121 }
122
123 template <typename T>
125 inline T Unpack() {
127 }
128
129 bool operator==(const Packet& right) const;
130 bool operator!=(const Packet& right) const;
131
132 private:
133 // Data stored in the packet
134 std::vector<uint8_t> packetData{};
135
136 size_t readPos = 0;
137 size_t writePos = 0;
138};
139
140template <typename T>
141concept arithmetic = std::integral<T> || std::floating_point<T>;
142
143// support encoding vectors
144template <typename T>
146struct SerdeType<std::vector<T>> {
147 static std::vector<T> Unpack(Packet& packet) {
148 uint8_t len = packet.Unpack<uint8_t>();
149 std::vector<T> ret;
150 ret.reserve(len);
151 for (size_t i = 0; i < len; i++) {
152 ret.push_back(packet.Unpack<T>());
153 }
154 return ret;
155 }
156 static void Pack(Packet& packet, const std::vector<T>& value) {
157 packet.Pack<uint8_t>(value.size());
158 for (const auto& thing : value) {
159 packet.Pack<T>(thing);
160 }
161 }
162 static constexpr std::string_view GetSchemaHash() {
163 // quick hack lol
165 }
166
167 static constexpr std::string_view GetSchema() {
168 // TODO: this gets us the plain type name of T, but this is not schema JSON
169 // compliant!
170 return "TODO[?]";
171 }
172};
173
174// support encoding optional types
175template <typename T>
176 requires(PhotonStructSerializable<T> || arithmetic<T>)
177struct SerdeType<std::optional<T>> {
178 static std::optional<T> Unpack(Packet& packet) {
179 if (packet.Unpack<uint8_t>() == 1u) {
180 return packet.Unpack<T>();
181 } else {
182 return std::nullopt;
183 }
184 }
185 static void Pack(Packet& packet, const std::optional<T>& value) {
186 packet.Pack<uint8_t>(value.has_value());
187 if (value) {
188 packet.Pack<T>(*value);
189 }
190 }
191 static constexpr std::string_view GetSchemaHash() {
192 // quick hack lol
194 }
195
196 static constexpr std::string_view GetSchema() {
197 // TODO: this gets us the plain type name of T, but this is not schema JSON
198 // compliant!
199 return "TODO?";
200 }
201};
202
203} // namespace photon
A packet that holds byte-packed data to be sent over NetworkTables.
Definition Packet.h:62
void Pack(const T &value)
Definition Packet.h:109
T Unpack()
Definition Packet.h:125
size_t GetDataSize() const
Returns the number of bytes in the data.
Definition Packet.h:90
T Unpack()
Definition Packet.h:115
bool operator==(const Packet &right) const
bool operator!=(const Packet &right) const
Packet(int initialCapacity=0)
Constructs an empty packet.
Definition Packet.h:67
void Pack(const T &value)
Definition Packet.h:94
const std::vector< uint8_t > & GetData()
Returns the packet data.
Definition Packet.h:84
void Clear()
Clears the packet and resets the read and write positions.
Packet(std::vector< uint8_t > data)
Constructs a packet with the given data.
Definition Packet.h:38
Definition Packet.h:141
Definition VisionEstimation.h:30
static void Pack(Packet &packet, const std::optional< T > &value)
Definition Packet.h:185
static std::optional< T > Unpack(Packet &packet)
Definition Packet.h:178
static constexpr std::string_view GetSchema()
Definition Packet.h:196
static constexpr std::string_view GetSchemaHash()
Definition Packet.h:191
static constexpr std::string_view GetSchema()
Definition Packet.h:167
static std::vector< T > Unpack(Packet &packet)
Definition Packet.h:147
static constexpr std::string_view GetSchemaHash()
Definition Packet.h:162
static void Pack(Packet &packet, const std::vector< T > &value)
Definition Packet.h:156
Definition Packet.h:35