WPILibC++ 2027.0.0-alpha-5
Loading...
Searching...
No Matches
ProtobufCallbacks.hpp
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 <ranges>
8#include <span>
9#include <utility>
10#include <vector>
11
12#include <fmt/format.h>
13
14#include "pb.h"
15#include "wpi/util/SmallVector.hpp"
16#include "wpi/util/array.hpp"
18
19namespace wpi::util {
20
21/**
22 * The behavior to use when more elements are in the message then expected when
23 * decoding.
24 */
25enum class DecodeLimits {
26 // Ignore any extra elements
28 // Add any extra elements to the backing vector
30 // Cause decoding to fail if extra elements exist
32};
33
34template <class T>
35concept StringLike = std::is_convertible_v<T, std::string_view>;
36
37template <class T>
38concept ConstVectorLike = std::is_convertible_v<T, std::span<const uint8_t>>;
39
40template <class T>
41concept MutableVectorLike = std::is_convertible_v<T, std::span<uint8_t>>;
42
43template <typename T>
45
46template <typename T>
47concept UnpackBytes = requires(T& t) {
48 { t.resize(size_t()) }; // NOLINT
49 { t.size() } -> std::same_as<size_t>;
50 { t.data() } -> std::convertible_to<void*>;
52
53template <typename T>
54concept ProtoEnumeration = std::is_enum_v<T>;
55
56template <typename T>
58 ProtoEnumeration<T> || std::integral<T> || std::floating_point<T>;
59
60template <typename T>
63
64template <typename T>
67
68namespace detail {
69
70template <typename T>
72
73template <Validatable T>
74constexpr bool ValidateType(pb_type_t type) {
75 switch (type) {
76 case PB_LTYPE_BOOL:
77 return std::integral<T>;
78 case PB_LTYPE_VARINT:
79 return std::signed_integral<T> || ProtoEnumeration<T>;
81 return std::unsigned_integral<T>;
83 return std::signed_integral<T>;
85 return std::integral<T> || std::floating_point<T>;
87 return std::integral<T> || std::floating_point<T>;
88 case PB_LTYPE_BYTES:
89 case PB_LTYPE_STRING:
93 default:
94 return false;
95 }
96}
97
98} // namespace detail
99
100/**
101 * A callback method that will directly unpack elements into
102 * the specified vector like data structure. The size passed
103 * is the expected number of elements.
104 *
105 * By default, any elements in the packed buffer past N will
106 * still be added to the vector.
107 *
108 * @tparam T object type
109 * @tparam U vector type to pack into
110 * @tparam N number of elements
111 */
112template <ProtoCallbackUnpackable T, typename U, size_t N = 1>
114 public:
115 /**
116 * Constructs a callback from a vector like type.
117 *
118 * @param storage the vector to store into
119 */
120 explicit DirectUnpackCallback(U& storage) : m_storage{storage} {
121 m_callback.funcs.decode = CallbackFunc;
122 m_callback.arg = this;
123 }
128
129 /**
130 * Set the limits on what happens if more elements exist in the buffer then
131 * expected.
132 *
133 * @param limit the limit to set
134 */
135 void SetLimits(DecodeLimits limit) noexcept { m_limits = limit; }
136
137 /**
138 * Gets the nanopb callback pointing to this object.
139 *
140 * @return nanopb callback
141 */
142 pb_callback_t Callback() const { return m_callback; }
143
144 private:
145 bool SizeCheck(bool* retVal) const {
146 if (m_storage.size() >= N) {
147 switch (m_limits) {
149 *retVal = true;
150 return false;
151
153 break;
154
155 default:
156 *retVal = false;
157 return false;
158 }
159 }
160 return true;
161 }
162
163 bool Decode(pb_istream_t* stream, pb_type_t fieldType) {
164 if constexpr (ProtoPackable<T>) {
165 switch (fieldType) {
166 case PB_LTYPE_BOOL:
167 if constexpr (std::integral<T>) {
168 bool val = false;
169 if (!pb_decode_bool(stream, &val)) {
170 return false;
171 }
172 m_storage.emplace_back(static_cast<T>(val));
173 return true;
174 } else {
175 return false;
176 }
177 case PB_LTYPE_VARINT:
178 if constexpr (std::signed_integral<T> || ProtoEnumeration<T>) {
179 int64_t val = 0;
180 if (!pb_decode_varint(stream, reinterpret_cast<uint64_t*>(&val))) {
181 return false;
182 }
183 m_storage.emplace_back(static_cast<T>(val));
184 return true;
185 } else {
186 return false;
187 }
188 case PB_LTYPE_UVARINT:
189 if constexpr (std::unsigned_integral<T>) {
190 uint64_t val = 0;
191 if (!pb_decode_varint(stream, &val)) {
192 return false;
193 }
194 m_storage.emplace_back(static_cast<T>(val));
195 return true;
196 } else {
197 return false;
198 }
199 case PB_LTYPE_SVARINT:
200 if constexpr (std::signed_integral<T>) {
201 int64_t val = 0;
202 if (!pb_decode_svarint(stream, &val)) {
203 return false;
204 }
205 m_storage.emplace_back(static_cast<T>(val));
206 return true;
207 } else {
208 return false;
209 }
210 case PB_LTYPE_FIXED32:
211 if constexpr (std::signed_integral<T>) {
212 int32_t val = 0;
213 if (!pb_decode_fixed32(stream, &val)) {
214 return false;
215 }
216 m_storage.emplace_back(static_cast<T>(val));
217 return true;
218 } else if constexpr (std::unsigned_integral<T>) {
219 uint32_t val = 0;
220 if (!pb_decode_fixed32(stream, &val)) {
221 return false;
222 }
223 m_storage.emplace_back(static_cast<T>(val));
224 return true;
225 }
226 if constexpr (std::floating_point<T>) {
227 float val = 0;
228 if (!pb_decode_fixed32(stream, &val)) {
229 return false;
230 }
231 m_storage.emplace_back(static_cast<T>(val));
232 return true;
233 } else {
234 return false;
235 }
236 case PB_LTYPE_FIXED64:
237 if constexpr (std::signed_integral<T>) {
238 int64_t val = 0;
239 if (!pb_decode_fixed64(stream, &val)) {
240 return false;
241 }
242 m_storage.emplace_back(static_cast<T>(val));
243 return true;
244 } else if constexpr (std::unsigned_integral<T>) {
245 uint64_t val = 0;
246 if (!pb_decode_fixed64(stream, &val)) {
247 return false;
248 }
249 m_storage.emplace_back(static_cast<T>(val));
250 return true;
251 }
252 if constexpr (std::floating_point<T>) {
253 double val = 0;
254 if (!pb_decode_fixed64(stream, &val)) {
255 return false;
256 }
257 m_storage.emplace_back(static_cast<T>(val));
258 return true;
259 } else {
260 return false;
261 }
262 default:
263 return false;
264 }
265 } else if constexpr (UnpackBytes<T>) {
266 T& space = m_storage.emplace_back(T{});
267 space.resize(stream->bytes_left);
268 return pb_read(stream, reinterpret_cast<pb_byte_t*>(space.data()),
269 space.size());
270 } else if constexpr (ProtobufSerializable<T>) {
271 ProtoInputStream<T> istream{stream};
272 auto decoded = wpi::util::Protobuf<T>::Unpack(istream);
273 if (decoded.has_value()) {
274 m_storage.emplace_back(std::move(decoded.value()));
275 return true;
276 }
277 return false;
278 }
279 }
280
281 bool CallbackFunc(pb_istream_t* stream, const pb_field_t* field) {
282 pb_type_t fieldType = PB_LTYPE(field->type);
283
284 if (!detail::ValidateType<T>(fieldType)) {
285 return false;
286 }
287
288 // Validate our types
289 if constexpr (ProtoPackable<T>) {
290 // Handle decode loop
291 while (stream->bytes_left > 0) {
292 bool sizeRetVal = 0;
293 if (!SizeCheck(&sizeRetVal)) {
294 return sizeRetVal;
295 }
296
297 if (!Decode(stream, fieldType)) {
298 return false;
299 }
300 }
301 return true;
302 } else {
303 // At this point, do the size check
304 bool sizeRetVal = 0;
305 if (!SizeCheck(&sizeRetVal)) {
306 return sizeRetVal;
307 }
308
309 // At this point, we're good to decode
310 return Decode(stream, fieldType);
311 }
312 }
313
314 static bool CallbackFunc(pb_istream_t* stream, const pb_field_t* field,
315 void** arg) {
316 return reinterpret_cast<DirectUnpackCallback*>(*arg)->CallbackFunc(stream,
317 field);
318 }
319
320 U& m_storage;
321 pb_callback_t m_callback;
323};
324
325/**
326 * A DirectUnpackCallback backed by a SmallVector<T, N>.
327 *
328 * By default, any elements in the packed buffer past N will
329 * be ignored, but decoding will still succeed
330 *
331 * @tparam T object type
332 * @tparam N small vector small size/number of expected elements
333 */
334template <ProtoCallbackUnpackable T, size_t N = 1>
336 : public DirectUnpackCallback<T, wpi::util::SmallVector<T, N>, N> {
337 public:
338 /**
339 * Constructs an UnpackCallback.
340 */
342 : DirectUnpackCallback<T, wpi::util::SmallVector<T, N>, N>{
343 m_storedBuffer} {
345 }
346
347 /**
348 * Gets a span pointing to the storage buffer.
349 *
350 * @return storage buffer span
351 */
352 std::span<T> Items() noexcept { return m_storedBuffer; }
353
354 /**
355 * Gets a const span pointing to the storage buffer.
356 *
357 * @return storage buffer span
358 */
359 std::span<const T> Items() const noexcept { return m_storedBuffer; }
360
361 /**
362 * Gets a reference to the backing small vector.
363 *
364 * @return small vector reference
365 */
366 wpi::util::SmallVector<T, N>& Vec() noexcept { return m_storedBuffer; }
367
368 private:
369 wpi::util::SmallVector<T, N> m_storedBuffer;
370};
371
372/**
373 * A DirectUnpackCallback backed by a std::vector.
374 *
375 * By default, any elements in the packed buffer past N will
376 * be ignored, but decoding will still succeed
377 *
378 * @tparam T object type
379 * @tparam N number of expected elements
380 */
381template <ProtoCallbackUnpackable T, size_t N = 1>
383 : public DirectUnpackCallback<T, std::vector<T>, N> {
384 public:
385 /**
386 * Constructs a StdVectorUnpackCallback.
387 */
389 : DirectUnpackCallback<T, std::vector<T>, N>{m_storedBuffer} {
391 }
392
393 /**
394 * Gets a span pointing to the storage buffer.
395 *
396 * @return storage buffer span
397 */
398 std::span<T> Items() noexcept { return m_storedBuffer; }
399
400 /**
401 * Gets a const span pointing to the storage buffer.
402 *
403 * @return storage buffer span
404 */
405 std::span<const T> Items() const noexcept { return m_storedBuffer; }
406
407 /**
408 * Gets a reference to the backing vector.
409 *
410 * @return vector reference
411 */
412 std::vector<T>& Vec() noexcept { return m_storedBuffer; }
413
414 private:
415 std::vector<T> m_storedBuffer;
416};
417
418/**
419 * A wrapper around a wpi::util::array that lets us
420 * treat it as a limited sized vector.
421 */
422template <ProtoCallbackUnpackable T, size_t N>
425 size_t m_currentIndex = 0;
426
427 size_t size() const { return m_currentIndex; }
428
429 template <typename... ArgTypes>
430 T& emplace_back(ArgTypes&&... Args) {
431 m_array[m_currentIndex] = T(std::forward<ArgTypes>(Args)...);
433 return m_array[m_currentIndex - 1];
434 }
435};
436
437/**
438 * A DirectUnpackCallback backed by a wpi::util::array<T, N>.
439 *
440 * Any elements in the packed buffer past N will
441 * be cause decoding to fail.
442 *
443 * @tparam T object type
444 * @tparam N small vector small size/number of expected elements
445 */
446template <ProtoCallbackUnpackable T, size_t N>
448 : public DirectUnpackCallback<T, WpiArrayEmplaceWrapper<T, N>, N> {
449 /**
450 * Constructs a WpiArrayUnpackCallback.
451 */
456
457 /**
458 * Returns if the buffer is completely filled up.
459 *
460 * @return true if buffer is full
461 */
462 bool IsFull() const noexcept { return m_array.m_currentIndex == N; }
463
464 /**
465 * Returns the number of elements in the buffer.
466 *
467 * @return number of elements
468 */
469 size_t Size() const noexcept { return m_array.m_currentIndex; }
470
471 /**
472 * Returns a reference to the backing array.
473 *
474 * @return array reference
475 */
476 wpi::util::array<T, N>& Array() noexcept { return m_array.m_array; }
477
478 private:
480};
481
482/**
483 * A callback method that will pack elements when called.
484 *
485 * @tparam T object type
486 * @tparam R range type (defaults to std::span<const T>)
487 */
488template <ProtoCallbackPackable T,
489 std::ranges::input_range R = std::span<const T>>
490 requires std::same_as<std::remove_cvref_t<std::ranges::range_value_t<R>>, T>
492 public:
493 /**
494 * Constructs a pack callback from a range of elements. The range
495 * _MUST_ stay alive throughout the entire encode call.
496 */
497 explicit PackCallback(const R& range)
498 requires(!std::same_as<R, std::span<const T>>)
499 : m_range{&range} {
500 m_callback.funcs.encode = CallbackFunc;
501 m_callback.arg = this;
502 }
503
504 /**
505 * Constructs a pack callback from a span of elements. The elements in the
506 * buffer _MUST_ stay alive throughout the entire encode call.
507 */
508 explicit PackCallback(std::span<const T> buffer)
509 requires std::same_as<R, std::span<const T>>
510 : m_storedSpan{buffer}, m_range{&m_storedSpan} {
511 m_callback.funcs.encode = CallbackFunc;
512 m_callback.arg = this;
513 }
514
515 /**
516 * Constructs a pack callback from a pointer to a single element.
517 * This element _MUST_ stay alive throughout the entire encode call.
518 * Do not pass a temporary here (This is why its a pointer and not a
519 * reference)
520 */
521 explicit PackCallback(const T* element)
522 requires std::same_as<R, std::span<const T>>
523 : PackCallback(std::span<const T>{element, 1}) {}
524
525 PackCallback(const PackCallback&) = delete;
529
530 /**
531 * Gets the nanopb callback pointing to this object.
532 *
533 * @return nanopb callback
534 */
535 pb_callback_t Callback() const { return m_callback; }
536
537 private:
538 static auto EncodeStreamTypeFinder() {
539 if constexpr (ProtobufSerializable<T>) {
540 return ProtoOutputStream<T>(nullptr);
541 } else {
542 return pb_ostream_t{};
543 }
544 }
545 using EncodeStreamType = decltype(EncodeStreamTypeFinder());
546
547 bool EncodeItem(EncodeStreamType& stream, const pb_field_t* field,
548 const T& value) const {
549 if constexpr (std::floating_point<T>) {
550 pb_type_t fieldType = PB_LTYPE(field->type);
551 switch (fieldType) {
552 case PB_LTYPE_FIXED32: {
553 float flt = static_cast<float>(value);
554 return pb_encode_fixed32(&stream, &flt);
555 }
556 case PB_LTYPE_FIXED64: {
557 double dbl = static_cast<double>(value);
558 return pb_encode_fixed64(&stream, &dbl);
559 }
560 default:
561 return false;
562 }
563 } else if constexpr (std::integral<T> || ProtoEnumeration<T>) {
564 pb_type_t fieldType = PB_LTYPE(field->type);
565 switch (fieldType) {
566 case PB_LTYPE_BOOL:
567 case PB_LTYPE_VARINT:
568 case PB_LTYPE_UVARINT:
569 return pb_encode_varint(&stream, value);
570 case PB_LTYPE_SVARINT:
571 return pb_encode_svarint(&stream, value);
572 case PB_LTYPE_FIXED32: {
573 uint32_t f = value;
574 return pb_encode_fixed32(&stream, &f);
575 }
576 case PB_LTYPE_FIXED64: {
577 uint64_t f = value;
578 return pb_encode_fixed64(&stream, &f);
579 }
580 default:
581 return false;
582 }
583 } else if constexpr (StringLike<T>) {
584 std::string_view view{value};
585 return pb_encode_string(&stream,
586 reinterpret_cast<const pb_byte_t*>(view.data()),
587 view.size());
588 } else if constexpr (ConstVectorLike<T>) {
589 std::span<const uint8_t> view{value};
590 return pb_encode_string(&stream,
591 reinterpret_cast<const pb_byte_t*>(view.data()),
592 view.size());
593 } else if constexpr (ProtobufSerializable<T>) {
594 return wpi::util::Protobuf<T>::Pack(stream, value);
595 }
596 }
597
598 bool EncodeLoop(pb_ostream_t* stream, const pb_field_t* field,
599 bool writeTag) const {
600 const R& range = *m_range;
601 if constexpr (ProtobufSerializable<T>) {
602 ProtoOutputStream<T> ostream{stream};
603 for (const auto& i : range) {
604 if (writeTag) {
605 if (!pb_encode_tag_for_field(stream, field)) {
606 return false;
607 }
608 }
609 if (!EncodeItem(ostream, field, i)) {
610 return false;
611 }
612 }
613 } else {
614 for (const auto& i : range) {
615 if (writeTag) {
616 if (!pb_encode_tag_for_field(stream, field)) {
617 return false;
618 }
619 }
620 if (!EncodeItem(*stream, field, i)) {
621 return false;
622 }
623 }
624 }
625 return true;
626 }
627
628 bool PackedEncode(pb_ostream_t* stream, const pb_field_t* field) const {
629 // We're always going to used packed encoding.
630 // So first we need to get the packed size.
631
633 if (!EncodeLoop(&substream, field, false)) {
634 return false;
635 }
636
637 // Encode as a string tag
638 if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) {
639 return false;
640 }
641
642 // Write length as varint
643 size_t size = substream.bytes_written;
644 if (!pb_encode_varint(stream, static_cast<uint64_t>(size))) {
645 return false;
646 }
647
648 return EncodeLoop(stream, field, false);
649 }
650
651 bool CallbackFunc(pb_ostream_t* stream, const pb_field_t* field) const {
652 // First off, if we're empty, do nothing, but say we were successful
653 if (std::ranges::empty(*m_range)) {
654 return true;
655 }
656
657 pb_type_t fieldType = PB_LTYPE(field->type);
658
659 if (!detail::ValidateType<T>(fieldType)) {
660 return false;
661 }
662
663 if constexpr (ProtoPackable<T>) {
664 return PackedEncode(stream, field);
665 } else {
666 return EncodeLoop(stream, field, true);
667 }
668 }
669
670 static bool CallbackFunc(pb_ostream_t* stream, const pb_field_t* field,
671 void* const* arg) {
672 return reinterpret_cast<const PackCallback*>(*arg)->CallbackFunc(stream,
673 field);
674 }
675
676 std::span<const T> m_storedSpan;
677 const R* m_range{nullptr};
678 pb_callback_t m_callback;
679};
680
681template <std::ranges::input_range R>
684
685template <ProtoCallbackPackable T>
687
688} // namespace wpi::util
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Returns a named argument to be used in a formatting function.
Definition base.h:2846
@ space
Definition base.h:689
void SetLimits(DecodeLimits limit) noexcept
Set the limits on what happens if more elements exist in the buffer then expected.
Definition ProtobufCallbacks.hpp:135
DirectUnpackCallback(U &storage)
Constructs a callback from a vector like type.
Definition ProtobufCallbacks.hpp:120
DirectUnpackCallback(DirectUnpackCallback &&)=delete
DirectUnpackCallback(const DirectUnpackCallback &)=delete
DirectUnpackCallback & operator=(DirectUnpackCallback &&)=delete
DirectUnpackCallback & operator=(const DirectUnpackCallback &)=delete
pb_callback_t Callback() const
Gets the nanopb callback pointing to this object.
Definition ProtobufCallbacks.hpp:142
A callback method that will pack elements when called.
Definition ProtobufCallbacks.hpp:491
PackCallback(std::span< const T > buffer)
Constructs a pack callback from a span of elements.
Definition ProtobufCallbacks.hpp:508
PackCallback & operator=(PackCallback &&)=delete
PackCallback & operator=(const PackCallback &)=delete
PackCallback(const T *element)
Constructs a pack callback from a pointer to a single element.
Definition ProtobufCallbacks.hpp:521
pb_callback_t Callback() const
Gets the nanopb callback pointing to this object.
Definition ProtobufCallbacks.hpp:535
PackCallback(const PackCallback &)=delete
PackCallback(PackCallback &&)=delete
PackCallback(const R &range)
Constructs a pack callback from a range of elements.
Definition ProtobufCallbacks.hpp:497
Class for wrapping a nanopb ostream.
Definition Protobuf.hpp:119
std::vector< T > & Vec() noexcept
Gets a reference to the backing vector.
Definition ProtobufCallbacks.hpp:412
std::span< T > Items() noexcept
Gets a span pointing to the storage buffer.
Definition ProtobufCallbacks.hpp:398
std::span< const T > Items() const noexcept
Gets a const span pointing to the storage buffer.
Definition ProtobufCallbacks.hpp:405
StdVectorUnpackCallback()
Constructs a StdVectorUnpackCallback.
Definition ProtobufCallbacks.hpp:388
UnpackCallback()
Constructs an UnpackCallback.
Definition ProtobufCallbacks.hpp:341
wpi::util::SmallVector< T, N > & Vec() noexcept
Gets a reference to the backing small vector.
Definition ProtobufCallbacks.hpp:366
std::span< T > Items() noexcept
Gets a span pointing to the storage buffer.
Definition ProtobufCallbacks.hpp:352
std::span< const T > Items() const noexcept
Gets a const span pointing to the storage buffer.
Definition ProtobufCallbacks.hpp:359
This class is a wrapper around std::array that does compile time size checking.
Definition array.hpp:26
Definition ProtobufCallbacks.hpp:38
Definition ProtobufCallbacks.hpp:41
Definition ProtobufCallbacks.hpp:44
Definition ProtobufCallbacks.hpp:61
Definition ProtobufCallbacks.hpp:65
Definition ProtobufCallbacks.hpp:54
Definition ProtobufCallbacks.hpp:57
Specifies that a type is capable of protobuf serialization and deserialization.
Definition Protobuf.hpp:252
Definition ProtobufCallbacks.hpp:35
Definition ProtobufCallbacks.hpp:47
Definition ProtobufCallbacks.hpp:71
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition printf.h:50
Definition StringMap.hpp:773
constexpr bool ValidateType(pb_type_t type)
Definition ProtobufCallbacks.hpp:74
Definition raw_os_ostream.hpp:19
DecodeLimits
The behavior to use when more elements are in the message then expected when decoding.
Definition ProtobufCallbacks.hpp:25
@ Fail
Definition ProtobufCallbacks.hpp:31
@ Add
Definition ProtobufCallbacks.hpp:29
@ Ignore
Definition ProtobufCallbacks.hpp:27
PackCallback(const R &) -> PackCallback< std::remove_cvref_t< std::ranges::range_value_t< R > >, R >
Definition CvSource.hpp:15
struct pb_ostream_s pb_ostream_t
Definition pb.h:318
uint_least8_t pb_byte_t
Definition pb.h:228
#define PB_LTYPE_STRING
Definition pb.h:256
#define PB_LTYPE_BOOL
Definition pb.h:240
#define PB_LTYPE_FIXED64
Definition pb.h:245
#define PB_LTYPE_SVARINT
Definition pb.h:243
pb_field_iter_t pb_field_t
Definition pb.h:369
#define PB_LTYPE_UVARINT
Definition pb.h:242
#define PB_LTYPE(x)
Definition pb.h:300
#define PB_LTYPE_VARINT
Definition pb.h:241
#define PB_LTYPE_BYTES
Definition pb.h:252
@ PB_WT_STRING
Definition pb.h:433
#define PB_LTYPE_FIXED32
Definition pb.h:244
struct pb_callback_s pb_callback_t
Definition pb.h:413
struct pb_istream_s pb_istream_t
Definition pb.h:317
#define PB_LTYPE_SUBMESSAGE
Definition pb.h:260
pb_byte_t pb_type_t
Definition pb.h:235
bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count)
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
bool pb_decode_bool(pb_istream_t *stream, bool *dest)
bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest)
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field)
#define PB_OSTREAM_SIZING
Definition pb_encode.h:124
bool pb_encode_varint(pb_ostream_t *stream, uint64_t value)
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value)
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number)
bool pb_encode_fixed32(pb_ostream_t *stream, const void *value)
bool pb_encode_svarint(pb_ostream_t *stream, int64_t value)
bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size)
union pb_callback_s::@361166177370034357342125062245131070012154074174 funcs
void * arg
Definition pb.h:424
bool(* encode)(pb_ostream_t *stream, const pb_field_t *field, void *const *arg)
Definition pb.h:420
pb_type_t type
Definition pb.h:359
pb_size_t tag
Definition pb.h:356
size_t bytes_left
Definition pb_decode.h:49
size_t bytes_written
Definition pb_encode.h:49
A wrapper around a wpi::util::array that lets us treat it as a limited sized vector.
Definition ProtobufCallbacks.hpp:423
size_t m_currentIndex
Definition ProtobufCallbacks.hpp:425
size_t size() const
Definition ProtobufCallbacks.hpp:427
T & emplace_back(ArgTypes &&... Args)
Definition ProtobufCallbacks.hpp:430
wpi::util::array< T, N > m_array
Definition ProtobufCallbacks.hpp:424
bool IsFull() const noexcept
Returns if the buffer is completely filled up.
Definition ProtobufCallbacks.hpp:462
size_t Size() const noexcept
Returns the number of elements in the buffer.
Definition ProtobufCallbacks.hpp:469
WpiArrayUnpackCallback()
Constructs a WpiArrayUnpackCallback.
Definition ProtobufCallbacks.hpp:452
wpi::util::array< T, N > & Array() noexcept
Returns a reference to the backing array.
Definition ProtobufCallbacks.hpp:476
Definition array.hpp:15