WPILibC++ 2024.3.2
Struct.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <stdint.h>
8
9#include <concepts>
10#include <memory>
11#include <span>
12#include <string>
13#include <string_view>
14#include <type_traits>
15#include <utility>
16#include <vector>
17
18#include <fmt/format.h>
19
20#include "wpi/Endian.h"
21#include "wpi/bit.h"
22#include "wpi/ct_string.h"
23#include "wpi/function_ref.h"
24#include "wpi/mutex.h"
25#include "wpi/type_traits.h"
26
27namespace wpi {
28
29/**
30 * Struct serialization template. Unspecialized class has no members; only
31 * specializations of this class are useful, and only if they meet the
32 * StructSerializable concept.
33 *
34 * @tparam T type to serialize/deserialize
35 * @tparam I optional struct type info
36 */
37template <typename T, typename... I>
38struct Struct {};
39
40/**
41 * Specifies that a type is capable of raw struct serialization and
42 * deserialization.
43 *
44 * This is designed for serializing small fixed-size data structures in the
45 * fastest and most compact means possible. Serialization consists of writing
46 * values into a mutable std::span and deserialization consists of reading
47 * values from an immutable std::span.
48 *
49 * Implementations must define a template specialization for wpi::Struct with
50 * T being the type that is being serialized/deserialized, with the following
51 * static members (as enforced by this concept):
52 * - std::string_view GetTypeString(): function that returns the type string
53 * - size_t GetSize(): function that returns the structure size in bytes
54 * - std::string_view GetSchema(): function that returns the struct schema
55 * - T Unpack(std::span<const uint8_t>): function for deserialization
56 * - void Pack(std::span<uint8_t>, T&& value): function for
57 * serialization
58 *
59 * If possible, the GetTypeString(), GetSize(), and GetSchema() functions should
60 * be marked constexpr. GetTypeString() and GetSchema() may return types other
61 * than std::string_view, as long as the return value is convertible to
62 * std::string_view.
63 *
64 * If the struct has nested structs, implementations should also meet the
65 * requirements of HasNestedStruct<T>.
66 */
67template <typename T, typename... I>
68concept StructSerializable = requires(std::span<const uint8_t> in,
69 std::span<uint8_t> out, T&& value,
70 const I&... info) {
71 typename Struct<typename std::remove_cvref_t<T>,
72 typename std::remove_cvref_t<I>...>;
73 {
74 Struct<typename std::remove_cvref_t<T>,
75 typename std::remove_cvref_t<I>...>::GetTypeString(info...)
76 } -> std::convertible_to<std::string_view>;
77 {
78 Struct<typename std::remove_cvref_t<T>,
79 typename std::remove_cvref_t<I>...>::GetSize(info...)
80 } -> std::convertible_to<size_t>;
81 {
82 Struct<typename std::remove_cvref_t<T>,
83 typename std::remove_cvref_t<I>...>::GetSchema(info...)
84 } -> std::convertible_to<std::string_view>;
85 {
86 Struct<typename std::remove_cvref_t<T>,
87 typename std::remove_cvref_t<I>...>::Unpack(in, info...)
88 } -> std::same_as<typename std::remove_cvref_t<T>>;
89 Struct<typename std::remove_cvref_t<T>,
90 typename std::remove_cvref_t<I>...>::Pack(out, std::forward<T>(value),
91 info...);
92};
93
94/**
95 * Specifies that a type is capable of in-place raw struct deserialization.
96 *
97 * In addition to meeting StructSerializable, implementations must define a
98 * wpi::Struct<T> static member `void UnpackInto(T*, std::span<const uint8_t>)`
99 * to update the pointed-to T with the contents of the span.
100 */
101template <typename T, typename... I>
103 StructSerializable<T, I...> &&
104 requires(T* out, std::span<const uint8_t> in, const I&... info) {
105 Struct<typename std::remove_cvref_t<T>,
106 typename std::remove_cvref_t<I>...>::UnpackInto(out, in, info...);
107 };
108
109/**
110 * Specifies that a struct type has nested struct declarations.
111 *
112 * In addition to meeting StructSerializable, implementations must define a
113 * wpi::Struct<T> static member
114 * `void ForEachNested(std::invocable<std::string_view, std::string_view) auto
115 * fn)` (or equivalent) and call ForEachNestedStruct<Type> on each nested struct
116 * type.
117 */
118template <typename T, typename... I>
120 StructSerializable<T, I...> &&
121 requires(function_ref<void(std::string_view, std::string_view)> fn,
122 const I&... info) {
123 Struct<typename std::remove_cvref_t<T>,
124 typename std::remove_cvref_t<I>...>::ForEachNested(fn, info...);
125 };
126
127/**
128 * Unpack a serialized struct.
129 *
130 * @tparam T object type
131 * @param data raw struct data
132 * @param info optional struct type info
133 * @return Deserialized object
134 */
135template <typename T, typename... I>
136 requires StructSerializable<T, I...>
137inline T UnpackStruct(std::span<const uint8_t> data, const I&... info) {
139 return S::Unpack(data, info...);
140}
141
142/**
143 * Unpack a serialized struct starting at a given offset within the data.
144 * This is primarily useful in unpack implementations to unpack nested structs.
145 *
146 * @tparam T object type
147 * @tparam Offset starting offset
148 * @param data raw struct data
149 * @param info optional struct type info
150 * @return Deserialized object
151 */
152template <typename T, size_t Offset, typename... I>
153 requires StructSerializable<T, I...>
154inline T UnpackStruct(std::span<const uint8_t> data, const I&... info) {
156 return S::Unpack(data.subspan(Offset), info...);
157}
158
159/**
160 * Pack a serialized struct.
161 *
162 * @param data struct storage (mutable, output)
163 * @param value object
164 * @param info optional struct type info
165 */
166template <typename T, typename... I>
167 requires StructSerializable<T, I...>
168inline void PackStruct(std::span<uint8_t> data, T&& value, const I&... info) {
170 typename std::remove_cvref_t<I>...>;
171 S::Pack(data, std::forward<T>(value), info...);
172}
173
174/**
175 * Pack a serialized struct starting at a given offset within the data. This is
176 * primarily useful in pack implementations to pack nested structs.
177 *
178 * @tparam Offset starting offset
179 * @param data struct storage (mutable, output)
180 * @param value object
181 * @param info optional struct type info
182 */
183template <size_t Offset, typename T, typename... I>
184 requires StructSerializable<T, I...>
185inline void PackStruct(std::span<uint8_t> data, T&& value, const I&... info) {
187 typename std::remove_cvref_t<I>...>;
188 S::Pack(data.subspan(Offset), std::forward<T>(value), info...);
189}
190
191/**
192 * Unpack a serialized struct into an existing object, overwriting its contents.
193 *
194 * @param out object (output)
195 * @param data raw struct data
196 * @param info optional struct type info
197 */
198template <typename T, typename... I>
199 requires StructSerializable<T, I...>
200inline void UnpackStructInto(T* out, std::span<const uint8_t> data,
201 const I&... info) {
203 if constexpr (MutableStructSerializable<T, I...>) {
204 S::UnpackInto(out, data, info...);
205 } else {
206 *out = UnpackStruct<T>(data, info...);
207 }
208}
209
210/**
211 * Unpack a serialized struct into an existing object, overwriting its contents,
212 * and starting at a given offset within the data.
213 * This is primarily useful in unpack implementations to unpack nested structs.
214 *
215 * @tparam Offset starting offset
216 * @param out object (output)
217 * @param data raw struct data
218 * @param info optional struct type info
219 */
220template <size_t Offset, typename T, typename... I>
221 requires StructSerializable<T, I...>
222inline void UnpackStructInto(T* out, std::span<const uint8_t> data,
223 const I&... info) {
225 if constexpr (MutableStructSerializable<T, I...>) {
226 S::UnpackInto(out, data.subspan(Offset), info...);
227 } else {
228 *out = UnpackStruct<T, Offset>(data, info...);
229 }
230}
231
232/**
233 * Get the type string for a raw struct serializable type
234 *
235 * @tparam T serializable type
236 * @param info optional struct type info
237 * @return type string
238 */
239template <typename T, typename... I>
240 requires StructSerializable<T, I...>
241constexpr auto GetStructTypeString(const I&... info) {
243 return S::GetTypeString(info...);
244}
245
246/**
247 * Get the size for a raw struct serializable type
248 *
249 * @tparam T serializable type
250 * @param info optional struct type info
251 * @return size
252 */
253template <typename T, typename... I>
254 requires StructSerializable<T, I...>
255constexpr size_t GetStructSize(const I&... info) {
257 return S::GetSize(info...);
258}
259
260template <typename T, size_t N, typename... I>
261 requires StructSerializable<T, I...>
262constexpr auto MakeStructArrayTypeString(const I&... info) {
264 if constexpr (sizeof...(I) == 0 &&
265 is_constexpr([&] { S::GetTypeString(info...); })) {
266 constexpr auto typeString = S::GetTypeString(info...);
267 using namespace literals;
268 if constexpr (N == std::dynamic_extent) {
269 return Concat(
270 ct_string<char, std::char_traits<char>, typeString.size()>{
271 typeString},
272 "[]"_ct_string);
273 } else {
274 return Concat(
275 ct_string<char, std::char_traits<char>, typeString.size()>{
276 typeString},
277 "["_ct_string, NumToCtString<N>(), "]"_ct_string);
278 }
279 } else {
280 if constexpr (N == std::dynamic_extent) {
281 return fmt::format("{}[]", S::GetTypeString(info...));
282 } else {
283 return fmt::format("{}[{}]", S::GetTypeString(info...), N);
284 }
285 }
286}
287
288template <typename T, size_t N, typename... I>
289 requires StructSerializable<T, I...>
290constexpr auto MakeStructArraySchema(const I&... info) {
292 if constexpr (sizeof...(I) == 0 &&
293 is_constexpr([&] { S::GetSchema(info...); })) {
294 constexpr auto schema = S::GetSchema(info...);
295 using namespace literals;
296 if constexpr (N == std::dynamic_extent) {
297 return Concat(
298 ct_string<char, std::char_traits<char>, schema.size()>{schema},
299 "[]"_ct_string);
300 } else {
301 return Concat(
302 ct_string<char, std::char_traits<char>, schema.size()>{schema},
303 "["_ct_string, NumToCtString<N>(), "]"_ct_string);
304 }
305 } else {
306 if constexpr (N == std::dynamic_extent) {
307 return fmt::format("{}[]", S::GetSchema(info...));
308 } else {
309 return fmt::format("{}[{}]", S::GetSchema(info...), N);
310 }
311 }
312}
313
314template <typename T, typename... I>
315 requires StructSerializable<T, I...>
316constexpr std::string_view GetStructSchema(const I&... info) {
318 return S::GetSchema(info...);
319}
320
321template <typename T, typename... I>
322 requires StructSerializable<T, I...>
323constexpr std::span<const uint8_t> GetStructSchemaBytes(const I&... info) {
325 auto schema = S::GetSchema(info...);
326 return {reinterpret_cast<const uint8_t*>(schema.data()), schema.size()};
327}
328
329template <typename T, typename... I>
330 requires StructSerializable<T, I...>
332 std::invocable<std::string_view, std::string_view> auto fn,
333 const I&... info) {
335 typename std::remove_cvref_t<I>...>;
336 if constexpr (HasNestedStruct<T, I...>) {
337 S::ForEachNested(fn, info...);
338 }
339 fn(S::GetTypeString(info...), S::GetSchema(info...));
340}
341
342template <typename T, typename... I>
343 requires StructSerializable<T, I...>
345 using S = Struct<T, I...>;
346
347 public:
348 StructArrayBuffer() = default;
351 StructArrayBuffer(StructArrayBuffer&& rhs) : m_buf{std::move(rhs.m_buf)} {}
353 m_buf = std::move(rhs.m_buf);
354 return *this;
355 }
356
357 template <typename U, typename F>
358 requires
359#if __cpp_lib_ranges >= 201911L
360 std::ranges::range<U> &&
361 std::convertible_to<std::ranges::range_value_t<U>, T> &&
362#endif
363 std::invocable<F, std::span<const uint8_t>>
364 void Write(U&& data, F&& func, const I&... info) {
365 auto size = S::GetSize(info...);
366 if ((std::size(data) * size) < 256) {
367 // use the stack
368 uint8_t buf[256];
369 auto out = buf;
370 for (auto&& val : data) {
371 S::Pack(std::span<uint8_t>{std::to_address(out), size},
372 std::forward<decltype(val)>(val), info...);
373 out += size;
374 }
375 func(std::span<uint8_t>{buf, out});
376 } else {
377 std::scoped_lock lock{m_mutex};
378 m_buf.resize(std::size(data) * size);
379 auto out = m_buf.begin();
380 for (auto&& val : data) {
381 S::Pack(std::span<uint8_t>{std::to_address(out), size},
382 std::forward<decltype(val)>(val), info...);
383 out += size;
384 }
385 func(m_buf);
386 }
387 }
388
389 private:
390 wpi::mutex m_mutex;
391 std::vector<uint8_t> m_buf;
392};
393
394/**
395 * Raw struct support for fixed-size arrays of other structs.
396 */
397template <typename T, size_t N, typename... I>
398 requires StructSerializable<T, I...>
399struct Struct<std::array<T, N>, I...> {
400 static constexpr auto GetTypeString(const I&... info) {
401 return MakeStructArrayTypeString<T, N>(info...);
402 }
403 static constexpr size_t GetSize(const I&... info) {
404 return N * GetStructSize<T>(info...);
405 }
406 static constexpr auto GetSchema(const I&... info) {
407 return MakeStructArraySchema<T, N>(info...);
408 }
409 static std::array<T, N> Unpack(std::span<const uint8_t> data,
410 const I&... info) {
411 auto size = GetStructSize<T>(info...);
412 std::array<T, N> result;
413 for (size_t i = 0; i < N; ++i) {
414 result[i] = UnpackStruct<T, 0>(data, info...);
415 data = data.subspan(size);
416 }
417 return result;
418 }
419 static void Pack(std::span<uint8_t> data, std::span<const T, N> values,
420 const I&... info) {
421 auto size = GetStructSize<T>(info...);
422 std::span<uint8_t> unsizedData = data;
423 for (auto&& val : values) {
424 PackStruct(unsizedData, val, info...);
425 unsizedData = unsizedData.subspan(size);
426 }
427 }
428 static void UnpackInto(std::array<T, N>* out, std::span<const uint8_t> data,
429 const I&... info) {
430 UnpackInto(std::span{*out}, data, info...);
431 }
432 // alternate span-based function
433 static void UnpackInto(std::span<T, N> out, std::span<const uint8_t> data,
434 const I&... info) {
435 auto size = GetStructSize<T>(info...);
436 std::span<const uint8_t> unsizedData = data;
437 for (size_t i = 0; i < N; ++i) {
438 UnpackStructInto(&out[i], unsizedData, info...);
439 unsizedData = unsizedData.subspan(size);
440 }
441 }
442};
443
444/**
445 * Raw struct support for boolean values.
446 * Primarily useful for higher level struct implementations.
447 */
448template <>
449struct Struct<bool> {
450 static constexpr std::string_view GetTypeString() { return "struct:bool"; }
451 static constexpr size_t GetSize() { return 1; }
452 static constexpr std::string_view GetSchema() { return "bool value"; }
453 static bool Unpack(std::span<const uint8_t> data) { return data[0]; }
454 static void Pack(std::span<uint8_t> data, bool value) {
455 data[0] = static_cast<char>(value ? 1 : 0);
456 }
457};
458
459/**
460 * Raw struct support for uint8_t values.
461 * Primarily useful for higher level struct implementations.
462 */
463template <>
464struct Struct<uint8_t> {
465 static constexpr std::string_view GetTypeString() { return "struct:uint8"; }
466 static constexpr size_t GetSize() { return 1; }
467 static constexpr std::string_view GetSchema() { return "uint8 value"; }
468 static uint8_t Unpack(std::span<const uint8_t> data) { return data[0]; }
469 static void Pack(std::span<uint8_t> data, uint8_t value) { data[0] = value; }
470};
471
472/**
473 * Raw struct support for int8_t values.
474 * Primarily useful for higher level struct implementations.
475 */
476template <>
477struct Struct<int8_t> {
478 static constexpr std::string_view GetTypeString() { return "struct:int8"; }
479 static constexpr size_t GetSize() { return 1; }
480 static constexpr std::string_view GetSchema() { return "int8 value"; }
481 static int8_t Unpack(std::span<const uint8_t, 1> data) { return data[0]; }
482 static void Pack(std::span<uint8_t, 1> data, int8_t value) {
483 data[0] = value;
484 }
485};
486
487/**
488 * Raw struct support for uint16_t values.
489 * Primarily useful for higher level struct implementations.
490 */
491template <>
492struct Struct<uint16_t> {
493 static constexpr std::string_view GetTypeString() { return "struct:uint16"; }
494 static constexpr size_t GetSize() { return 2; }
495 static constexpr std::string_view GetSchema() { return "uint16 value"; }
496 static uint16_t Unpack(std::span<const uint8_t> data) {
497 return support::endian::read16le(data.data());
498 }
499 static void Pack(std::span<uint8_t> data, uint16_t value) {
500 support::endian::write16le(data.data(), value);
501 }
502};
503
504/**
505 * Raw struct support for int16_t values.
506 * Primarily useful for higher level struct implementations.
507 */
508template <>
509struct Struct<int16_t> {
510 static constexpr std::string_view GetTypeString() { return "struct:int16"; }
511 static constexpr size_t GetSize() { return 2; }
512 static constexpr std::string_view GetSchema() { return "int16 value"; }
513 static int16_t Unpack(std::span<const uint8_t> data) {
514 return support::endian::read16le(data.data());
515 }
516 static void Pack(std::span<uint8_t> data, int16_t value) {
517 support::endian::write16le(data.data(), value);
518 }
519};
520
521/**
522 * Raw struct support for uint32_t values.
523 * Primarily useful for higher level struct implementations.
524 */
525template <>
526struct Struct<uint32_t> {
527 static constexpr std::string_view GetTypeString() { return "struct:uint32"; }
528 static constexpr size_t GetSize() { return 4; }
529 static constexpr std::string_view GetSchema() { return "uint32 value"; }
530 static uint32_t Unpack(std::span<const uint8_t> data) {
531 return support::endian::read32le(data.data());
532 }
533 static void Pack(std::span<uint8_t> data, uint32_t value) {
534 support::endian::write32le(data.data(), value);
535 }
536};
537
538/**
539 * Raw struct support for int32_t values.
540 * Primarily useful for higher level struct implementations.
541 */
542template <>
543struct Struct<int32_t> {
544 static constexpr std::string_view GetTypeString() { return "struct:int32"; }
545 static constexpr size_t GetSize() { return 4; }
546 static constexpr std::string_view GetSchema() { return "int32 value"; }
547 static int32_t Unpack(std::span<const uint8_t> data) {
548 return support::endian::read32le(data.data());
549 }
550 static void Pack(std::span<uint8_t> data, int32_t value) {
551 support::endian::write32le(data.data(), value);
552 }
553};
554
555/**
556 * Raw struct support for uint64_t values.
557 * Primarily useful for higher level struct implementations.
558 */
559template <>
560struct Struct<uint64_t> {
561 static constexpr std::string_view GetTypeString() { return "struct:uint64"; }
562 static constexpr size_t GetSize() { return 8; }
563 static constexpr std::string_view GetSchema() { return "uint64 value"; }
564 static uint64_t Unpack(std::span<const uint8_t> data) {
565 return support::endian::read64le(data.data());
566 }
567 static void Pack(std::span<uint8_t> data, uint64_t value) {
568 support::endian::write64le(data.data(), value);
569 }
570};
571
572/**
573 * Raw struct support for int64_t values.
574 * Primarily useful for higher level struct implementations.
575 */
576template <>
577struct Struct<int64_t> {
578 static constexpr std::string_view GetTypeString() { return "struct:int64"; }
579 static constexpr size_t GetSize() { return 8; }
580 static constexpr std::string_view GetSchema() { return "int64 value"; }
581 static int64_t Unpack(std::span<const uint8_t> data) {
582 return support::endian::read64le(data.data());
583 }
584 static void Pack(std::span<uint8_t> data, int64_t value) {
585 support::endian::write64le(data.data(), value);
586 }
587};
588
589/**
590 * Raw struct support for float values.
591 * Primarily useful for higher level struct implementations.
592 */
593template <>
594struct Struct<float> {
595 static constexpr std::string_view GetTypeString() { return "struct:float"; }
596 static constexpr size_t GetSize() { return 4; }
597 static constexpr std::string_view GetSchema() { return "float value"; }
598 static float Unpack(std::span<const uint8_t> data) {
599 return bit_cast<float>(support::endian::read32le(data.data()));
600 }
601 static void Pack(std::span<uint8_t> data, float value) {
602 support::endian::write32le(data.data(), bit_cast<uint32_t>(value));
603 }
604};
605
606/**
607 * Raw struct support for double values.
608 * Primarily useful for higher level struct implementations.
609 */
610template <>
611struct Struct<double> {
612 static constexpr std::string_view GetTypeString() { return "struct:double"; }
613 static constexpr size_t GetSize() { return 8; }
614 static constexpr std::string_view GetSchema() { return "double value"; }
615 static double Unpack(std::span<const uint8_t> data) {
616 return bit_cast<double>(support::endian::read64le(data.data()));
617 }
618 static void Pack(std::span<uint8_t> data, double value) {
619 support::endian::write64le(data.data(), bit_cast<uint64_t>(value));
620 }
621};
622
623} // namespace wpi
This file implements the C++20 <bit> header.
Definition: Struct.h:344
void Write(U &&data, F &&func, const I &... info)
Definition: Struct.h:364
StructArrayBuffer(StructArrayBuffer &&rhs)
Definition: Struct.h:351
StructArrayBuffer & operator=(StructArrayBuffer &&rhs)
Definition: Struct.h:352
StructArrayBuffer(const StructArrayBuffer &)=delete
StructArrayBuffer & operator=(const StructArrayBuffer &)=delete
This class is a wrapper around std::array that does compile time size checking.
Definition: array.h:26
Specifies that a struct type has nested struct declarations.
Definition: Struct.h:119
Specifies that a type is capable of in-place raw struct deserialization.
Definition: Struct.h:102
Specifies that a type is capable of raw struct serialization and deserialization.
Definition: Struct.h:68
basic_string_view< char > string_view
Definition: core.h:501
constexpr auto in(type t, int set) -> bool
Definition: core.h:611
Definition: xchar.h:71
Definition: array.h:89
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
std::string GetTypeString(const google::protobuf::Message &msg)
uint32_t read32le(const void *P)
Definition: Endian.h:383
uint64_t read64le(const void *P)
Definition: Endian.h:384
void write32le(void *P, uint32_t V)
Definition: Endian.h:418
uint16_t read16le(const void *P)
Definition: Endian.h:382
void write64le(void *P, uint64_t V)
Definition: Endian.h:419
void write16le(void *P, uint16_t V)
Definition: Endian.h:417
Definition: ntcore_cpp.h:26
constexpr auto GetStructTypeString(const I &... info)
Get the type string for a raw struct serializable type.
Definition: Struct.h:241
constexpr auto Concat(ct_string< Char, Traits, N1 > const &s1, ct_string< Char, Traits, N > const &... s)
Concatenates multiple fixed_strings into a larger fixed_string at compile time.
Definition: ct_string.h:168
constexpr auto MakeStructArraySchema(const I &... info)
Definition: Struct.h:290
void UnpackStructInto(T *out, std::span< const uint8_t > data, const I &... info)
Unpack a serialized struct into an existing object, overwriting its contents.
Definition: Struct.h:200
constexpr auto MakeStructArrayTypeString(const I &... info)
Definition: Struct.h:262
T UnpackStruct(std::span< const uint8_t > data, const I &... info)
Unpack a serialized struct.
Definition: Struct.h:137
constexpr std::span< const uint8_t > GetStructSchemaBytes(const I &... info)
Definition: Struct.h:323
constexpr std::string_view GetStructSchema(const I &... info)
Definition: Struct.h:316
constexpr size_t GetStructSize(const I &... info)
Get the size for a raw struct serializable type.
Definition: Struct.h:255
void ForEachStructSchema(std::invocable< std::string_view, std::string_view > auto fn, const I &... info)
Definition: Struct.h:331
constexpr bool is_constexpr(Lambda)
Definition: type_traits.h:81
void PackStruct(std::span< uint8_t > data, T &&value, const I &... info)
Pack a serialized struct.
Definition: Struct.h:168
static constexpr size_t GetSize()
Definition: Struct.h:451
static constexpr std::string_view GetTypeString()
Definition: Struct.h:450
static constexpr std::string_view GetSchema()
Definition: Struct.h:452
static bool Unpack(std::span< const uint8_t > data)
Definition: Struct.h:453
static void Pack(std::span< uint8_t > data, bool value)
Definition: Struct.h:454
static constexpr std::string_view GetTypeString()
Definition: Struct.h:612
static void Pack(std::span< uint8_t > data, double value)
Definition: Struct.h:618
static constexpr std::string_view GetSchema()
Definition: Struct.h:614
static double Unpack(std::span< const uint8_t > data)
Definition: Struct.h:615
static constexpr size_t GetSize()
Definition: Struct.h:613
static constexpr std::string_view GetSchema()
Definition: Struct.h:597
static constexpr std::string_view GetTypeString()
Definition: Struct.h:595
static float Unpack(std::span< const uint8_t > data)
Definition: Struct.h:598
static void Pack(std::span< uint8_t > data, float value)
Definition: Struct.h:601
static constexpr size_t GetSize()
Definition: Struct.h:596
static constexpr size_t GetSize()
Definition: Struct.h:511
static int16_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:513
static void Pack(std::span< uint8_t > data, int16_t value)
Definition: Struct.h:516
static constexpr std::string_view GetTypeString()
Definition: Struct.h:510
static constexpr std::string_view GetSchema()
Definition: Struct.h:512
static void Pack(std::span< uint8_t > data, int32_t value)
Definition: Struct.h:550
static constexpr size_t GetSize()
Definition: Struct.h:545
static int32_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:547
static constexpr std::string_view GetTypeString()
Definition: Struct.h:544
static constexpr std::string_view GetSchema()
Definition: Struct.h:546
static constexpr size_t GetSize()
Definition: Struct.h:579
static constexpr std::string_view GetSchema()
Definition: Struct.h:580
static constexpr std::string_view GetTypeString()
Definition: Struct.h:578
static void Pack(std::span< uint8_t > data, int64_t value)
Definition: Struct.h:584
static int64_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:581
static void Pack(std::span< uint8_t, 1 > data, int8_t value)
Definition: Struct.h:482
static constexpr std::string_view GetSchema()
Definition: Struct.h:480
static constexpr size_t GetSize()
Definition: Struct.h:479
static int8_t Unpack(std::span< const uint8_t, 1 > data)
Definition: Struct.h:481
static constexpr std::string_view GetTypeString()
Definition: Struct.h:478
static void UnpackInto(std::array< T, N > *out, std::span< const uint8_t > data, const I &... info)
Definition: Struct.h:428
static std::array< T, N > Unpack(std::span< const uint8_t > data, const I &... info)
Definition: Struct.h:409
static constexpr auto GetTypeString(const I &... info)
Definition: Struct.h:400
static void UnpackInto(std::span< T, N > out, std::span< const uint8_t > data, const I &... info)
Definition: Struct.h:433
static constexpr size_t GetSize(const I &... info)
Definition: Struct.h:403
static constexpr auto GetSchema(const I &... info)
Definition: Struct.h:406
static void Pack(std::span< uint8_t > data, std::span< const T, N > values, const I &... info)
Definition: Struct.h:419
static constexpr std::string_view GetTypeString()
Definition: Struct.h:493
static void Pack(std::span< uint8_t > data, uint16_t value)
Definition: Struct.h:499
static constexpr size_t GetSize()
Definition: Struct.h:494
static constexpr std::string_view GetSchema()
Definition: Struct.h:495
static uint16_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:496
static uint32_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:530
static void Pack(std::span< uint8_t > data, uint32_t value)
Definition: Struct.h:533
static constexpr std::string_view GetSchema()
Definition: Struct.h:529
static constexpr std::string_view GetTypeString()
Definition: Struct.h:527
static constexpr size_t GetSize()
Definition: Struct.h:528
static constexpr std::string_view GetTypeString()
Definition: Struct.h:561
static uint64_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:564
static constexpr size_t GetSize()
Definition: Struct.h:562
static constexpr std::string_view GetSchema()
Definition: Struct.h:563
static void Pack(std::span< uint8_t > data, uint64_t value)
Definition: Struct.h:567
static constexpr std::string_view GetSchema()
Definition: Struct.h:467
static void Pack(std::span< uint8_t > data, uint8_t value)
Definition: Struct.h:469
static uint8_t Unpack(std::span< const uint8_t > data)
Definition: Struct.h:468
static constexpr std::string_view GetTypeString()
Definition: Struct.h:465
static constexpr size_t GetSize()
Definition: Struct.h:466
Struct serialization template.
Definition: Struct.h:38
Fixed length string (array of character) for compile time use.
Definition: ct_string.h:29
constexpr auto size() const noexcept
Definition: ct_string.h:124
static void Pack(std::span< uint8_t > data, const frc::DifferentialDriveWheelVoltages &value)
static void ForEachNested(std::invocable< std::string_view, std::string_view > auto fn)
Definition: Transform3dStruct.h:27
static constexpr std::string_view GetTypeString()
Definition: DifferentialDriveWheelVoltagesStruct.h:14
static constexpr std::string_view GetSchema()
Definition: DifferentialDriveWheelVoltagesStruct.h:18
static frc::DifferentialDriveWheelVoltages Unpack(std::span< const uint8_t > data)
static constexpr size_t GetSize()
Definition: DifferentialDriveWheelVoltagesStruct.h:17
::std::mutex mutex
Definition: mutex.h:17
#define S(label, offset, message)
Definition: Errors.h:119
auto format(wformat_string< T... > fmt, T &&... args) -> std::wstring
Definition: xchar.h:108