WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
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/array.h"
22#include "wpi/bit.h"
23#include "wpi/ct_string.h"
24#include "wpi/function_ref.h"
25#include "wpi/mutex.h"
26#include "wpi/type_traits.h"
27
28namespace wpi {
29
30/**
31 * Struct serialization template. Unspecialized class has no members; only
32 * specializations of this class are useful, and only if they meet the
33 * StructSerializable concept.
34 *
35 * @tparam T type to serialize/deserialize
36 * @tparam I optional struct type info
37 */
38template <typename T, typename... I>
39struct Struct {};
40
41/**
42 * Specifies that a type is capable of raw struct serialization and
43 * deserialization.
44 *
45 * This is designed for serializing small fixed-size data structures in the
46 * fastest and most compact means possible. Serialization consists of writing
47 * values into a mutable std::span and deserialization consists of reading
48 * values from an immutable std::span.
49 *
50 * Implementations must define a template specialization for wpi::Struct with
51 * T being the type that is being serialized/deserialized, with the following
52 * static members (as enforced by this concept):
53 * - std::string_view GetTypeName(): function that returns the type name
54 * - size_t GetSize(): function that returns the structure size in bytes
55 * - std::string_view GetSchema(): function that returns the struct schema
56 * - T Unpack(std::span<const uint8_t>): function for deserialization
57 * - void Pack(std::span<uint8_t>, T&& value): function for
58 * serialization
59 *
60 * If possible, the GetTypeName(), GetSize(), and GetSchema() functions should
61 * be marked constexpr. GetTypeName() and GetSchema() may return types other
62 * than std::string_view, as long as the return value is convertible to
63 * std::string_view.
64 *
65 * If the struct has nested structs, implementations should also meet the
66 * requirements of HasNestedStruct<T>.
67 */
68template <typename T, typename... I>
69concept StructSerializable = requires(std::span<const uint8_t> in,
70 std::span<uint8_t> out, T&& value,
71 const I&... info) {
72 typename Struct<typename std::remove_cvref_t<T>,
73 typename std::remove_cvref_t<I>...>;
74 {
75 Struct<typename std::remove_cvref_t<T>,
76 typename std::remove_cvref_t<I>...>::GetTypeName(info...)
77 } -> std::convertible_to<std::string_view>;
78 {
79 Struct<typename std::remove_cvref_t<T>,
80 typename std::remove_cvref_t<I>...>::GetSize(info...)
81 } -> std::convertible_to<size_t>;
82 {
83 Struct<typename std::remove_cvref_t<T>,
84 typename std::remove_cvref_t<I>...>::GetSchema(info...)
85 } -> std::convertible_to<std::string_view>;
86 {
87 Struct<typename std::remove_cvref_t<T>,
88 typename std::remove_cvref_t<I>...>::Unpack(in, info...)
89 } -> std::same_as<typename std::remove_cvref_t<T>>;
90 Struct<typename std::remove_cvref_t<T>,
91 typename std::remove_cvref_t<I>...>::Pack(out, std::forward<T>(value),
92 info...);
93};
94
95/**
96 * Specifies that a type is capable of in-place raw struct deserialization.
97 *
98 * In addition to meeting StructSerializable, implementations must define a
99 * wpi::Struct<T> static member `void UnpackInto(T*, std::span<const uint8_t>)`
100 * to update the pointed-to T with the contents of the span.
101 */
102template <typename T, typename... I>
104 StructSerializable<T, I...> &&
105 requires(T* out, std::span<const uint8_t> in, const I&... info) {
106 Struct<typename std::remove_cvref_t<T>,
107 typename std::remove_cvref_t<I>...>::UnpackInto(out, in, info...);
108 };
109
110/**
111 * Specifies that a struct type has nested struct declarations.
112 *
113 * In addition to meeting StructSerializable, implementations must define a
114 * wpi::Struct<T> static member
115 * `void ForEachNested(std::invocable<std::string_view, std::string_view) auto
116 * fn)` (or equivalent) and call ForEachStructSchema<Type> on each nested struct
117 * type.
118 */
119template <typename T, typename... I>
121 StructSerializable<T, I...> &&
122 requires(function_ref<void(std::string_view, std::string_view)> fn,
123 const I&... info) {
124 Struct<typename std::remove_cvref_t<T>,
125 typename std::remove_cvref_t<I>...>::ForEachNested(fn, info...);
126 };
127
128/**
129 * Unpack a serialized struct.
130 *
131 * @tparam T object type
132 * @param data raw struct data
133 * @param info optional struct type info
134 * @return Deserialized object
135 */
136template <typename T, typename... I>
137 requires StructSerializable<T, I...>
138inline T UnpackStruct(std::span<const uint8_t> data, const I&... info) {
140 return S::Unpack(data, info...);
141}
142
143/**
144 * Unpack a serialized struct starting at a given offset within the data.
145 * This is primarily useful in unpack implementations to unpack nested structs.
146 *
147 * @tparam T object type
148 * @tparam Offset starting offset
149 * @param data raw struct data
150 * @param info optional struct type info
151 * @return Deserialized object
152 */
153template <typename T, size_t Offset, typename... I>
154 requires StructSerializable<T, I...>
155inline T UnpackStruct(std::span<const uint8_t> data, const I&... info) {
157 return S::Unpack(data.subspan(Offset), info...);
158}
159
160/**
161 * Unpack a serialized struct array starting at a given offset within the data.
162 * This is primarily useful in unpack implementations to unpack nested struct
163 * arrays.
164 *
165 * @tparam T object type
166 * @tparam Offset starting offset
167 * @tparam N number of objects
168 * @param data raw struct data
169 * @return Deserialized array
170 */
171template <StructSerializable T, size_t Offset, size_t N>
172inline wpi::array<T, N> UnpackStructArray(std::span<const uint8_t> data) {
173 if (is_constexpr([] { Struct<std::remove_cvref_t<T>>::GetSize(); })) {
174 constexpr auto StructSize = Struct<std::remove_cvref_t<T>>::GetSize();
176 [&]<size_t... Is>(std::index_sequence<Is...>) {
177 ((arr[Is] = UnpackStruct<T, Offset + Is * StructSize>(data)), ...);
178 }(std::make_index_sequence<N>{});
179 return arr;
180 } else {
181 auto size = Struct<std::remove_cvref_t<T>>::GetSize();
183 for (size_t i = 0; i < N; i++) {
184 arr[i] = UnpackStruct<T>(data);
185 data = data.subspan(size);
186 }
187 return arr;
188 }
189}
190
191/**
192 * Pack a serialized struct.
193 *
194 * @param data struct storage (mutable, output)
195 * @param value object
196 * @param info optional struct type info
197 */
198template <typename T, typename... I>
199 requires StructSerializable<T, I...>
200inline void PackStruct(std::span<uint8_t> data, T&& value, const I&... info) {
202 typename std::remove_cvref_t<I>...>;
203 S::Pack(data, std::forward<T>(value), info...);
204}
205
206/**
207 * Pack a serialized struct starting at a given offset within the data. This is
208 * primarily useful in pack implementations to pack nested structs.
209 *
210 * @tparam Offset starting offset
211 * @param data struct storage (mutable, output)
212 * @param value object
213 * @param info optional struct type info
214 */
215template <size_t Offset, typename T, typename... I>
216 requires StructSerializable<T, I...>
217inline void PackStruct(std::span<uint8_t> data, T&& value, const I&... info) {
219 typename std::remove_cvref_t<I>...>;
220 S::Pack(data.subspan(Offset), std::forward<T>(value), info...);
221}
222
223/**
224 * Pack a serialized struct array starting at a given offset within the data.
225 * This is primarily useful in pack implementations to pack nested struct
226 * arrays.
227 *
228 * @tparam Offset starting offset
229 * @tparam N number of objects
230 * @param data struct storage (mutable, output)
231 * @param arr array of object
232 */
233template <size_t Offset, size_t N, StructSerializable T>
234inline void PackStructArray(std::span<uint8_t> data,
235 const wpi::array<T, N>& arr) {
236 if (is_constexpr([] { Struct<std::remove_cvref_t<T>>::GetSize(); })) {
237 constexpr auto StructSize = Struct<std::remove_cvref_t<T>>::GetSize();
238 [&]<size_t... Is>(std::index_sequence<Is...>) {
239 (PackStruct<Offset + Is * StructSize>(data, arr[Is]), ...);
240 }(std::make_index_sequence<N>{});
241 } else {
242 auto size = Struct<std::remove_cvref_t<T>>::GetSize();
243 for (auto&& val : arr) {
244 PackStruct(data, val);
245 data = data.subspan(size);
246 }
247 }
248}
249
250/**
251 * Unpack a serialized struct into an existing object, overwriting its contents.
252 *
253 * @param out object (output)
254 * @param data raw struct data
255 * @param info optional struct type info
256 */
257template <typename T, typename... I>
258 requires StructSerializable<T, I...>
259inline void UnpackStructInto(T* out, std::span<const uint8_t> data,
260 const I&... info) {
262 if constexpr (MutableStructSerializable<T, I...>) {
263 S::UnpackInto(out, data, info...);
264 } else {
265 *out = UnpackStruct<T>(data, info...);
266 }
267}
268
269/**
270 * Unpack a serialized struct into an existing object, overwriting its contents,
271 * and starting at a given offset within the data.
272 * This is primarily useful in unpack implementations to unpack nested structs.
273 *
274 * @tparam Offset starting offset
275 * @param out object (output)
276 * @param data raw struct data
277 * @param info optional struct type info
278 */
279template <size_t Offset, typename T, typename... I>
280 requires StructSerializable<T, I...>
281inline void UnpackStructInto(T* out, std::span<const uint8_t> data,
282 const I&... info) {
284 if constexpr (MutableStructSerializable<T, I...>) {
285 S::UnpackInto(out, data.subspan(Offset), info...);
286 } else {
287 *out = UnpackStruct<T, Offset>(data, info...);
288 }
289}
290
291/**
292 * Get the type name for a raw struct serializable type
293 *
294 * @tparam T serializable type
295 * @param info optional struct type info
296 * @return type name
297 */
298template <typename T, typename... I>
299 requires StructSerializable<T, I...>
300constexpr auto GetStructTypeName(const I&... info) {
302 return S::GetTypeName(info...);
303}
304
305/**
306 * Get the type string for a raw struct serializable type
307 *
308 * @tparam T serializable type
309 * @param info optional struct type info
310 * @return type string (struct: followed by type name)
311 */
312template <typename T, typename... I>
313 requires StructSerializable<T, I...>
314constexpr auto GetStructTypeString(const I&... info) {
316 if constexpr (sizeof...(I) == 0 &&
317 is_constexpr([&] { S::GetTypeName(info...); })) {
318 constexpr auto typeName = S::GetTypeName(info...);
319 using namespace literals;
320 return Concat(
321 "struct:"_ct_string,
322 ct_string<char, std::char_traits<char>, typeName.size()>{typeName});
323 } else {
324 return fmt::format("struct:{}", S::GetTypeName(info...));
325 }
326}
327
328/**
329 * Get the size for a raw struct serializable type
330 *
331 * @tparam T serializable type
332 * @param info optional struct type info
333 * @return size
334 */
335template <typename T, typename... I>
336 requires StructSerializable<T, I...>
337constexpr size_t GetStructSize(const I&... info) {
339 return S::GetSize(info...);
340}
341
342template <typename T, size_t N, typename... I>
343 requires StructSerializable<T, I...>
344constexpr auto MakeStructArrayTypeName(const I&... info) {
346 if constexpr (sizeof...(I) == 0 &&
347 is_constexpr([&] { S::GetTypeName(info...); })) {
348 constexpr auto typeName = S::GetTypeName(info...);
349 using namespace literals;
350 if constexpr (N == std::dynamic_extent) {
351 return Concat(
352 ct_string<char, std::char_traits<char>, typeName.size()>{typeName},
353 "[]"_ct_string);
354 } else {
355 return Concat(
356 ct_string<char, std::char_traits<char>, typeName.size()>{typeName},
357 "["_ct_string, NumToCtString<N>(), "]"_ct_string);
358 }
359 } else {
360 if constexpr (N == std::dynamic_extent) {
361 return fmt::format("{}[]", S::GetTypeName(info...));
362 } else {
363 return fmt::format("{}[{}]", S::GetTypeName(info...), N);
364 }
365 }
366}
367
368template <typename T, size_t N, typename... I>
369 requires StructSerializable<T, I...>
370constexpr auto MakeStructArrayTypeString(const I&... info) {
372 if constexpr (sizeof...(I) == 0 &&
373 is_constexpr([&] { S::GetTypeName(info...); })) {
374 using namespace literals;
375 return Concat("struct:"_ct_string, MakeStructArrayTypeName<T, N>(info...));
376 } else {
377 return fmt::format("struct:{}", MakeStructArrayTypeName<T, N>(info...));
378 }
379}
380
381template <typename T, size_t N, typename... I>
382 requires StructSerializable<T, I...>
383constexpr auto MakeStructArraySchema(const I&... info) {
385 if constexpr (sizeof...(I) == 0 &&
386 is_constexpr([&] { S::GetSchema(info...); })) {
387 constexpr auto schema = S::GetSchema(info...);
388 using namespace literals;
389 if constexpr (N == std::dynamic_extent) {
390 return Concat(
391 ct_string<char, std::char_traits<char>, schema.size()>{schema},
392 "[]"_ct_string);
393 } else {
394 return Concat(
395 ct_string<char, std::char_traits<char>, schema.size()>{schema},
396 "["_ct_string, NumToCtString<N>(), "]"_ct_string);
397 }
398 } else {
399 if constexpr (N == std::dynamic_extent) {
400 return fmt::format("{}[]", S::GetSchema(info...));
401 } else {
402 return fmt::format("{}[{}]", S::GetSchema(info...), N);
403 }
404 }
405}
406
407template <typename T, typename... I>
408 requires StructSerializable<T, I...>
409constexpr std::string_view GetStructSchema(const I&... info) {
411 return S::GetSchema(info...);
412}
413
414template <typename T, typename... I>
415 requires StructSerializable<T, I...>
416constexpr std::span<const uint8_t> GetStructSchemaBytes(const I&... info) {
418 auto schema = S::GetSchema(info...);
419 return {reinterpret_cast<const uint8_t*>(schema.data()), schema.size()};
420}
421
422template <typename T, typename... I>
423 requires StructSerializable<T, I...>
425 std::invocable<std::string_view, std::string_view> auto fn,
426 const I&... info) {
428 typename std::remove_cvref_t<I>...>;
429 if constexpr (HasNestedStruct<T, I...>) {
430 S::ForEachNested(fn, info...);
431 }
432 fn(GetStructTypeString<T>(info...), S::GetSchema(info...));
433}
434
435template <typename T, typename... I>
436 requires StructSerializable<T, I...>
438 using S = Struct<T, I...>;
439
440 public:
441 StructArrayBuffer() = default;
444 StructArrayBuffer(StructArrayBuffer&& rhs) : m_buf{std::move(rhs.m_buf)} {}
446 m_buf = std::move(rhs.m_buf);
447 return *this;
448 }
449
450 template <typename U, typename F>
451 requires
452#if __cpp_lib_ranges >= 201911L
453 std::ranges::range<U> &&
454 std::convertible_to<std::ranges::range_value_t<U>, T> &&
455#endif
456 std::invocable<F, std::span<const uint8_t>>
457 void Write(U&& data, F&& func, const I&... info) {
458 auto size = S::GetSize(info...);
459 if ((std::size(data) * size) < 256) {
460 // use the stack
461 uint8_t buf[256];
462 auto out = buf;
463 for (auto&& val : data) {
464 S::Pack(std::span<uint8_t>{std::to_address(out), size},
465 std::forward<decltype(val)>(val), info...);
466 out += size;
467 }
468 func(std::span<uint8_t>{buf, out});
469 } else {
470 std::scoped_lock lock{m_mutex};
471 m_buf.resize(std::size(data) * size);
472 auto out = m_buf.begin();
473 for (auto&& val : data) {
474 S::Pack(std::span<uint8_t>{std::to_address(out), size},
475 std::forward<decltype(val)>(val), info...);
476 out += size;
477 }
478 func(m_buf);
479 }
480 }
481
482 private:
483 wpi::mutex m_mutex;
484 std::vector<uint8_t> m_buf;
485};
486
487/**
488 * Raw struct support for fixed-size arrays of other structs.
489 */
490template <typename T, size_t N, typename... I>
491 requires StructSerializable<T, I...>
492struct Struct<std::array<T, N>, I...> {
493 static constexpr auto GetTypeName(const I&... info) {
494 return MakeStructArrayTypeName<T, N>(info...);
495 }
496 static constexpr size_t GetSize(const I&... info) {
497 return N * GetStructSize<T>(info...);
498 }
499 static constexpr auto GetSchema(const I&... info) {
500 return MakeStructArraySchema<T, N>(info...);
501 }
502 static std::array<T, N> Unpack(std::span<const uint8_t> data,
503 const I&... info) {
504 auto size = GetStructSize<T>(info...);
505 std::array<T, N> result;
506 for (size_t i = 0; i < N; ++i) {
507 result[i] = UnpackStruct<T, 0>(data, info...);
508 data = data.subspan(size);
509 }
510 return result;
511 }
512 static void Pack(std::span<uint8_t> data, std::span<const T, N> values,
513 const I&... info) {
514 auto size = GetStructSize<T>(info...);
515 std::span<uint8_t> unsizedData = data;
516 for (auto&& val : values) {
517 PackStruct(unsizedData, val, info...);
518 unsizedData = unsizedData.subspan(size);
519 }
520 }
521 static void UnpackInto(std::array<T, N>* out, std::span<const uint8_t> data,
522 const I&... info) {
523 UnpackInto(std::span{*out}, data, info...);
524 }
525 // alternate span-based function
526 static void UnpackInto(std::span<T, N> out, std::span<const uint8_t> data,
527 const I&... info) {
528 auto size = GetStructSize<T>(info...);
529 std::span<const uint8_t> unsizedData = data;
530 for (size_t i = 0; i < N; ++i) {
531 UnpackStructInto(&out[i], unsizedData, info...);
532 unsizedData = unsizedData.subspan(size);
533 }
534 }
535};
536
537/**
538 * Raw struct support for boolean values.
539 * Primarily useful for higher level struct implementations.
540 */
541template <>
542struct Struct<bool> {
543 static constexpr std::string_view GetTypeName() { return "bool"; }
544 static constexpr size_t GetSize() { return 1; }
545 static constexpr std::string_view GetSchema() { return "bool value"; }
546 static bool Unpack(std::span<const uint8_t> data) { return data[0]; }
547 static void Pack(std::span<uint8_t> data, bool value) {
548 data[0] = static_cast<char>(value ? 1 : 0);
549 }
550};
551
552/**
553 * Raw struct support for uint8_t values.
554 * Primarily useful for higher level struct implementations.
555 */
556template <>
557struct Struct<uint8_t> {
558 static constexpr std::string_view GetTypeName() { return "uint8"; }
559 static constexpr size_t GetSize() { return 1; }
560 static constexpr std::string_view GetSchema() { return "uint8 value"; }
561 static uint8_t Unpack(std::span<const uint8_t> data) { return data[0]; }
562 static void Pack(std::span<uint8_t> data, uint8_t value) { data[0] = value; }
563};
564
565/**
566 * Raw struct support for int8_t values.
567 * Primarily useful for higher level struct implementations.
568 */
569template <>
570struct Struct<int8_t> {
571 static constexpr std::string_view GetTypeName() { return "int8"; }
572 static constexpr size_t GetSize() { return 1; }
573 static constexpr std::string_view GetSchema() { return "int8 value"; }
574 static int8_t Unpack(std::span<const uint8_t> data) { return data[0]; }
575 static void Pack(std::span<uint8_t> data, int8_t value) { data[0] = value; }
576};
577
578/**
579 * Raw struct support for uint16_t values.
580 * Primarily useful for higher level struct implementations.
581 */
582template <>
583struct Struct<uint16_t> {
584 static constexpr std::string_view GetTypeName() { return "uint16"; }
585 static constexpr size_t GetSize() { return 2; }
586 static constexpr std::string_view GetSchema() { return "uint16 value"; }
587 static uint16_t Unpack(std::span<const uint8_t> data) {
588 return support::endian::read16le(data.data());
589 }
590 static void Pack(std::span<uint8_t> data, uint16_t value) {
591 support::endian::write16le(data.data(), value);
592 }
593};
594
595/**
596 * Raw struct support for int16_t values.
597 * Primarily useful for higher level struct implementations.
598 */
599template <>
600struct Struct<int16_t> {
601 static constexpr std::string_view GetTypeName() { return "int16"; }
602 static constexpr size_t GetSize() { return 2; }
603 static constexpr std::string_view GetSchema() { return "int16 value"; }
604 static int16_t Unpack(std::span<const uint8_t> data) {
605 return support::endian::read16le(data.data());
606 }
607 static void Pack(std::span<uint8_t> data, int16_t value) {
608 support::endian::write16le(data.data(), value);
609 }
610};
611
612/**
613 * Raw struct support for uint32_t values.
614 * Primarily useful for higher level struct implementations.
615 */
616template <>
617struct Struct<uint32_t> {
618 static constexpr std::string_view GetTypeName() { return "uint32"; }
619 static constexpr size_t GetSize() { return 4; }
620 static constexpr std::string_view GetSchema() { return "uint32 value"; }
621 static uint32_t Unpack(std::span<const uint8_t> data) {
622 return support::endian::read32le(data.data());
623 }
624 static void Pack(std::span<uint8_t> data, uint32_t value) {
625 support::endian::write32le(data.data(), value);
626 }
627};
628
629/**
630 * Raw struct support for int32_t values.
631 * Primarily useful for higher level struct implementations.
632 */
633template <>
634struct Struct<int32_t> {
635 static constexpr std::string_view GetTypeName() { return "int32"; }
636 static constexpr size_t GetSize() { return 4; }
637 static constexpr std::string_view GetSchema() { return "int32 value"; }
638 static int32_t Unpack(std::span<const uint8_t> data) {
639 return support::endian::read32le(data.data());
640 }
641 static void Pack(std::span<uint8_t> data, int32_t value) {
642 support::endian::write32le(data.data(), value);
643 }
644};
645
646/**
647 * Raw struct support for uint64_t values.
648 * Primarily useful for higher level struct implementations.
649 */
650template <>
651struct Struct<uint64_t> {
652 static constexpr std::string_view GetTypeName() { return "uint64"; }
653 static constexpr size_t GetSize() { return 8; }
654 static constexpr std::string_view GetSchema() { return "uint64 value"; }
655 static uint64_t Unpack(std::span<const uint8_t> data) {
656 return support::endian::read64le(data.data());
657 }
658 static void Pack(std::span<uint8_t> data, uint64_t value) {
659 support::endian::write64le(data.data(), value);
660 }
661};
662
663/**
664 * Raw struct support for int64_t values.
665 * Primarily useful for higher level struct implementations.
666 */
667template <>
668struct Struct<int64_t> {
669 static constexpr std::string_view GetTypeName() { return "int64"; }
670 static constexpr size_t GetSize() { return 8; }
671 static constexpr std::string_view GetSchema() { return "int64 value"; }
672 static int64_t Unpack(std::span<const uint8_t> data) {
673 return support::endian::read64le(data.data());
674 }
675 static void Pack(std::span<uint8_t> data, int64_t value) {
676 support::endian::write64le(data.data(), value);
677 }
678};
679
680/**
681 * Raw struct support for float values.
682 * Primarily useful for higher level struct implementations.
683 */
684template <>
685struct Struct<float> {
686 static constexpr std::string_view GetTypeName() { return "float"; }
687 static constexpr size_t GetSize() { return 4; }
688 static constexpr std::string_view GetSchema() { return "float value"; }
689 static float Unpack(std::span<const uint8_t> data) {
690 return bit_cast<float>(support::endian::read32le(data.data()));
691 }
692 static void Pack(std::span<uint8_t> data, float value) {
694 }
695};
696
697/**
698 * Raw struct support for double values.
699 * Primarily useful for higher level struct implementations.
700 */
701template <>
702struct Struct<double> {
703 static constexpr std::string_view GetTypeName() { return "double"; }
704 static constexpr size_t GetSize() { return 8; }
705 static constexpr std::string_view GetSchema() { return "double value"; }
706 static double Unpack(std::span<const uint8_t> data) {
707 return bit_cast<double>(support::endian::read64le(data.data()));
708 }
709 static void Pack(std::span<uint8_t> data, double value) {
711 }
712};
713
714} // namespace wpi
This file implements the C++20 <bit> header.
Definition Struct.h:437
void Write(U &&data, F &&func, const I &... info)
Definition Struct.h:457
StructArrayBuffer(StructArrayBuffer &&rhs)
Definition Struct.h:444
StructArrayBuffer & operator=(StructArrayBuffer &&rhs)
Definition Struct.h:445
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:120
Specifies that a type is capable of in-place raw struct deserialization.
Definition Struct.h:103
Specifies that a type is capable of raw struct serialization and deserialization.
Definition Struct.h:69
Definition json.h:5183
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
uint32_t read32le(const void *P)
Definition Endian.h:427
uint64_t read64le(const void *P)
Definition Endian.h:430
void write32le(void *P, uint32_t V)
Definition Endian.h:470
uint16_t read16le(const void *P)
Definition Endian.h:424
void write64le(void *P, uint64_t V)
Definition Endian.h:473
void write16le(void *P, uint16_t V)
Definition Endian.h:467
Foonathan namespace.
Definition ntcore_cpp.h:26
constexpr auto GetStructTypeString(const I &... info)
Get the type string for a raw struct serializable type.
Definition Struct.h:314
constexpr auto MakeStructArrayTypeName(const I &... info)
Definition Struct.h:344
constexpr auto NumToCtString()
Converts any integral to a ct_string at compile-time.
Definition ct_string.h:202
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:383
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:259
constexpr auto MakeStructArrayTypeString(const I &... info)
Definition Struct.h:370
T UnpackStruct(std::span< const uint8_t > data, const I &... info)
Unpack a serialized struct.
Definition Struct.h:138
constexpr std::span< const uint8_t > GetStructSchemaBytes(const I &... info)
Definition Struct.h:416
void PackStructArray(std::span< uint8_t > data, const wpi::array< T, N > &arr)
Pack a serialized struct array starting at a given offset within the data.
Definition Struct.h:234
constexpr std::string_view GetStructSchema(const I &... info)
Definition Struct.h:409
constexpr auto GetStructTypeName(const I &... info)
Get the type name for a raw struct serializable type.
Definition Struct.h:300
constexpr empty_array_t empty_array
Definition array.h:16
constexpr size_t GetStructSize(const I &... info)
Get the size for a raw struct serializable type.
Definition Struct.h:337
void ForEachStructSchema(std::invocable< std::string_view, std::string_view > auto fn, const I &... info)
Definition Struct.h:424
To bit_cast(const From &from) noexcept
Definition bit.h:51
wpi::array< T, N > UnpackStructArray(std::span< const uint8_t > data)
Unpack a serialized struct array starting at a given offset within the data.
Definition Struct.h:172
constexpr bool is_constexpr(Lambda)
Definition type_traits.h:81
::std::mutex mutex
Definition mutex.h:17
std::string GetTypeName(const T &type)
Returns the type name of an object.
Definition Demangle.h:27
void PackStruct(std::span< uint8_t > data, T &&value, const I &... info)
Pack a serialized struct.
Definition Struct.h:200
static constexpr size_t GetSize()
Definition Struct.h:544
static constexpr std::string_view GetSchema()
Definition Struct.h:545
static bool Unpack(std::span< const uint8_t > data)
Definition Struct.h:546
static constexpr std::string_view GetTypeName()
Definition Struct.h:543
static void Pack(std::span< uint8_t > data, bool value)
Definition Struct.h:547
static void Pack(std::span< uint8_t > data, double value)
Definition Struct.h:709
static constexpr std::string_view GetSchema()
Definition Struct.h:705
static constexpr std::string_view GetTypeName()
Definition Struct.h:703
static double Unpack(std::span< const uint8_t > data)
Definition Struct.h:706
static constexpr size_t GetSize()
Definition Struct.h:704
static constexpr std::string_view GetSchema()
Definition Struct.h:688
static float Unpack(std::span< const uint8_t > data)
Definition Struct.h:689
static void Pack(std::span< uint8_t > data, float value)
Definition Struct.h:692
static constexpr size_t GetSize()
Definition Struct.h:687
static constexpr std::string_view GetTypeName()
Definition Struct.h:686
static constexpr size_t GetSize()
Definition Struct.h:602
static int16_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:604
static void Pack(std::span< uint8_t > data, int16_t value)
Definition Struct.h:607
static constexpr std::string_view GetSchema()
Definition Struct.h:603
static constexpr std::string_view GetTypeName()
Definition Struct.h:601
static void Pack(std::span< uint8_t > data, int32_t value)
Definition Struct.h:641
static constexpr size_t GetSize()
Definition Struct.h:636
static int32_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:638
static constexpr std::string_view GetSchema()
Definition Struct.h:637
static constexpr std::string_view GetTypeName()
Definition Struct.h:635
static constexpr size_t GetSize()
Definition Struct.h:670
static constexpr std::string_view GetSchema()
Definition Struct.h:671
static constexpr std::string_view GetTypeName()
Definition Struct.h:669
static void Pack(std::span< uint8_t > data, int64_t value)
Definition Struct.h:675
static int64_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:672
static constexpr std::string_view GetTypeName()
Definition Struct.h:571
static int8_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:574
static void Pack(std::span< uint8_t > data, int8_t value)
Definition Struct.h:575
static constexpr std::string_view GetSchema()
Definition Struct.h:573
static constexpr size_t GetSize()
Definition Struct.h:572
static void UnpackInto(std::array< T, N > *out, std::span< const uint8_t > data, const I &... info)
Definition Struct.h:521
static std::array< T, N > Unpack(std::span< const uint8_t > data, const I &... info)
Definition Struct.h:502
static void UnpackInto(std::span< T, N > out, std::span< const uint8_t > data, const I &... info)
Definition Struct.h:526
static constexpr auto GetTypeName(const I &... info)
Definition Struct.h:493
static constexpr size_t GetSize(const I &... info)
Definition Struct.h:496
static constexpr auto GetSchema(const I &... info)
Definition Struct.h:499
static void Pack(std::span< uint8_t > data, std::span< const T, N > values, const I &... info)
Definition Struct.h:512
static void Pack(std::span< uint8_t > data, uint16_t value)
Definition Struct.h:590
static constexpr size_t GetSize()
Definition Struct.h:585
static constexpr std::string_view GetTypeName()
Definition Struct.h:584
static constexpr std::string_view GetSchema()
Definition Struct.h:586
static uint16_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:587
static uint32_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:621
static constexpr std::string_view GetTypeName()
Definition Struct.h:618
static void Pack(std::span< uint8_t > data, uint32_t value)
Definition Struct.h:624
static constexpr std::string_view GetSchema()
Definition Struct.h:620
static constexpr size_t GetSize()
Definition Struct.h:619
static uint64_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:655
static constexpr size_t GetSize()
Definition Struct.h:653
static constexpr std::string_view GetSchema()
Definition Struct.h:654
static void Pack(std::span< uint8_t > data, uint64_t value)
Definition Struct.h:658
static constexpr std::string_view GetTypeName()
Definition Struct.h:652
static constexpr std::string_view GetSchema()
Definition Struct.h:560
static void Pack(std::span< uint8_t > data, uint8_t value)
Definition Struct.h:562
static uint8_t Unpack(std::span< const uint8_t > data)
Definition Struct.h:561
static constexpr std::string_view GetTypeName()
Definition Struct.h:558
static constexpr size_t GetSize()
Definition Struct.h:559
Struct serialization template.
Definition Struct.h:39
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
#define S(label, offset, message)
Definition Errors.h:113