C/C++ API Reference
Loading...
Searching...
No Matches
stream_decoder.h
1// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <cstring>
17#include <limits>
18#include <type_traits>
19
20#include "pw_assert/assert.h"
21#include "pw_containers/vector.h"
22#include "pw_protobuf/internal/codegen.h"
23#include "pw_protobuf/wire_format.h"
24#include "pw_span/span.h"
25#include "pw_status/status.h"
26#include "pw_status/status_with_size.h"
27#include "pw_stream/stream.h"
28#include "pw_varint/stream.h"
29#include "pw_varint/varint.h"
30
31namespace pw::protobuf {
32
34
35// A low-level, event-based protobuf wire format decoder that operates on a
36// stream.
37//
38// The decoder processes an encoded message by iterating over its fields. The
39// caller can extract the values of any fields it cares about.
40//
41// The decoder does not provide any in-memory data structures to represent a
42// protobuf message's data. More sophisticated APIs can be built on top of the
43// low-level decoder to provide additional functionality, if desired.
44//
45// **NOTE**
46// This decoder is intended to be used for protobuf messages which are too large
47// to fit in memory. For smaller messages, prefer the MemoryDecoder, which is
48// much more efficient.
49//
50// Example usage:
51//
52// stream::Reader& my_stream = GetProtoStream();
53// StreamDecoder decoder(my_stream);
54//
55// while (decoder.Next().ok()) {
56// // FieldNumber() will always be valid if Next() returns OK.
57// switch (decoder.FieldNumber().value()) {
58// case 1:
59// Result<uint32_t> result = decoder.ReadUint32();
60// if (result.ok()) {
61// DoSomething(result.value());
62// }
63// break;
64// // ... and other fields.
65// }
66// }
67//
69 public:
70 // stream::Reader for a bytes field in a streamed proto message.
71 //
72 // Shares the StreamDecoder's reader, limiting it to the bounds of a bytes
73 // field. If the StreamDecoder's reader does not supporting seeking, this
74 // will also not.
76 public:
77 ~BytesReader() override { decoder_.CloseBytesReader(*this); }
78
79 constexpr size_t field_size() const { return end_offset_ - start_offset_; }
80
81 private:
82 friend class StreamDecoder;
83
84 constexpr BytesReader(StreamDecoder& decoder,
85 size_t start_offset,
86 size_t end_offset)
87 : decoder_(decoder),
88 start_offset_(start_offset),
89 end_offset_(end_offset),
90 status_(OkStatus()) {}
91
92 constexpr BytesReader(StreamDecoder& decoder, Status status)
93 : decoder_(decoder),
94 start_offset_(0),
95 end_offset_(0),
96 status_(status) {}
97
98 StatusWithSize DoRead(ByteSpan destination) final;
99 Status DoSeek(ptrdiff_t offset, Whence origin) final;
100
101 StreamDecoder& decoder_;
102 size_t start_offset_;
103 size_t end_offset_;
104 Status status_;
105 };
106
107 constexpr StreamDecoder(stream::Reader& reader)
108 : StreamDecoder(reader, std::numeric_limits<size_t>::max()) {}
109
110 // Allow the maximum length of the protobuf to be specified to the decoder
111 // for streaming situations. When constructed in this way, the decoder will
112 // consume any remaining bytes when it goes out of scope.
113 constexpr StreamDecoder(stream::Reader& reader, size_t length)
114 : reader_(reader),
115 stream_bounds_({0, length}),
116 position_(0),
117 current_field_(kInitialFieldKey),
118 delimited_field_size_(0),
119 delimited_field_offset_(0),
120 parent_(nullptr),
121 field_consumed_(true),
122 nested_reader_open_(false),
123 status_(OkStatus()) {}
124
125 StreamDecoder(const StreamDecoder& other) = delete;
126 StreamDecoder& operator=(const StreamDecoder& other) = delete;
127
128 ~StreamDecoder();
129
130 // Advances to the next field in the proto.
131 //
132 // If Next() returns OK, there is guaranteed to be a valid protobuf field at
133 // the current position, which can then be consumed through one of the Read*
134 // methods.
135 //
136 // Return values:
137 //
138 // OK: Advanced to a valid proto field.
139 // OUT_OF_RANGE: Reached the end of the proto message.
140 // DATA_LOSS: Invalid protobuf data.
141 //
142 Status Next();
143
144 // Returns the field number of the current field.
145 //
146 // Can only be called after a successful call to Next() and before any
147 // Read*() operation.
148 constexpr Result<uint32_t> FieldNumber() const {
149 if (field_consumed_) {
151 }
152
153 return status_.ok() ? current_field_.field_number()
154 : Result<uint32_t>(status_);
155 }
156
157 //
158 // TODO(frolv): Add Status Read*(T& value) APIs alongside the Result<T> ones.
159 //
160
161 // Reads a proto int32 value from the current position.
162 Result<int32_t> ReadInt32() {
163 return ReadVarintField<int32_t>(internal::VarintType::kNormal);
164 }
165
166 // Reads repeated int32 values from the current position using packed
167 // encoding.
168 //
169 // Returns the number of values read. In the case of error, the return value
170 // indicates the number of values successfully read, in addition to the error.
171 StatusWithSize ReadPackedInt32(span<int32_t> out) {
172 return ReadPackedVarintField(
173 as_writable_bytes(out), sizeof(int32_t), internal::VarintType::kNormal);
174 }
175
176 // Reads repeated int32 values from the current position into the vector,
177 // supporting either repeated single field elements or packed encoding.
178 Status ReadRepeatedInt32(pw::Vector<int32_t>& out) {
179 return ReadRepeatedVarintField<int32_t>(out, internal::VarintType::kNormal);
180 }
181
182 // Reads a proto uint32 value from the current position.
183 Result<uint32_t> ReadUint32() {
184 return ReadVarintField<uint32_t>(internal::VarintType::kUnsigned);
185 }
186
187 // Reads repeated uint32 values from the current position using packed
188 // encoding.
189 //
190 // Returns the number of values read. In the case of error, the return value
191 // indicates the number of values successfully read, in addition to the error.
192 StatusWithSize ReadPackedUint32(span<uint32_t> out) {
193 return ReadPackedVarintField(as_writable_bytes(out),
194 sizeof(uint32_t),
195 internal::VarintType::kUnsigned);
196 }
197
198 // Reads repeated uint32 values from the current position into the vector,
199 // supporting either repeated single field elements or packed encoding.
200 Status ReadRepeatedUint32(pw::Vector<uint32_t>& out) {
201 return ReadRepeatedVarintField<uint32_t>(out,
202 internal::VarintType::kUnsigned);
203 }
204
205 // Reads repeated enum values from the current position using packed
206 // encoding.
207 template <typename T, typename = std::enable_if_t<std::is_enum_v<T>>>
208 StatusWithSize ReadPackedEnum(span<T> out) {
209 static_assert(sizeof(T) == sizeof(int32_t),
210 "Protobuf enums are always 4-byte integers");
211 return ReadPackedVarintField(
212 as_writable_bytes(out), sizeof(T), internal::VarintType::kUnsigned);
213 }
214
215 // Reads repeated enum values from the current position into the vector,
216 // supporting either repeated single field elements or packed encoding.
217 template <typename T, typename = std::enable_if_t<std::is_enum_v<T>>>
218 Status ReadRepeatedEnum(pw::Vector<T>& out) {
219 static_assert(sizeof(T) == sizeof(int32_t),
220 "Protobuf enums are always 4-byte integers");
221 if (out.full()) {
223 }
224 const size_t old_size = out.size();
225 out.resize(out.capacity());
226 size_t size = old_size;
227 Status status =
228 ReadRepeatedVarintFieldGeneric(reinterpret_cast<std::byte*>(out.data()),
229 out.capacity(),
230 size,
231 sizeof(T),
232 internal::VarintType::kUnsigned);
233 out.resize(size);
234 return status;
235 }
236
237 // Reads a proto int64 value from the current position.
238 Result<int64_t> ReadInt64() {
239 return ReadVarintField<int64_t>(internal::VarintType::kNormal);
240 }
241
242 // Reads repeated int64 values from the current position using packed
243 // encoding.
244 //
245 // Returns the number of values read. In the case of error, the return value
246 // indicates the number of values successfully read, in addition to the
247 // error.
248 StatusWithSize ReadPackedInt64(span<int64_t> out) {
249 return ReadPackedVarintField(
250 as_writable_bytes(out), sizeof(int64_t), internal::VarintType::kNormal);
251 }
252
253 // Reads repeated int64 values from the current position into the vector,
254 // supporting either repeated single field elements or packed encoding.
255 Status ReadRepeatedInt64(pw::Vector<int64_t>& out) {
256 return ReadRepeatedVarintField<int64_t>(out, internal::VarintType::kNormal);
257 }
258
259 // Reads a proto uint64 value from the current position.
260 Result<uint64_t> ReadUint64() {
261 return ReadVarintField<uint64_t>(internal::VarintType::kUnsigned);
262 }
263
264 // Reads repeated uint64 values from the current position using packed
265 // encoding.
266 //
267 // Returns the number of values read. In the case of error, the return value
268 // indicates the number of values successfully read, in addition to the
269 // error.
270 StatusWithSize ReadPackedUint64(span<uint64_t> out) {
271 return ReadPackedVarintField(as_writable_bytes(out),
272 sizeof(uint64_t),
273 internal::VarintType::kUnsigned);
274 }
275
276 // Reads repeated uint64 values from the current position into the vector,
277 // supporting either repeated single field elements or packed encoding.
278 Status ReadRepeatedUint64(pw::Vector<uint64_t>& out) {
279 return ReadRepeatedVarintField<uint64_t>(out,
280 internal::VarintType::kUnsigned);
281 }
282
283 // Reads a proto sint32 value from the current position.
284 Result<int32_t> ReadSint32() {
285 return ReadVarintField<int32_t>(internal::VarintType::kZigZag);
286 }
287
288 // Reads repeated sint32 values from the current position using packed
289 // encoding.
290 //
291 // Returns the number of values read. In the case of error, the return value
292 // indicates the number of values successfully read, in addition to the
293 // error.
294 StatusWithSize ReadPackedSint32(span<int32_t> out) {
295 return ReadPackedVarintField(
296 as_writable_bytes(out), sizeof(int32_t), internal::VarintType::kZigZag);
297 }
298
299 // Reads repeated sint32 values from the current position into the vector,
300 // supporting either repeated single field elements or packed encoding.
301 Status ReadRepeatedSint32(pw::Vector<int32_t>& out) {
302 return ReadRepeatedVarintField<int32_t>(out, internal::VarintType::kZigZag);
303 }
304
305 // Reads a proto sint64 value from the current position.
306 Result<int64_t> ReadSint64() {
307 return ReadVarintField<int64_t>(internal::VarintType::kZigZag);
308 }
309
310 // Reads repeated int64 values from the current position using packed
311 // encoding.
312 //
313 // Returns the number of values read. In the case of error, the return value
314 // indicates the number of values successfully read, in addition to the
315 // error.
316 StatusWithSize ReadPackedSint64(span<int64_t> out) {
317 return ReadPackedVarintField(
318 as_writable_bytes(out), sizeof(int64_t), internal::VarintType::kZigZag);
319 }
320
321 // Reads repeated sint64 values from the current position into the vector,
322 // supporting either repeated single field elements or packed encoding.
323 Status ReadRepeatedSint64(pw::Vector<int64_t>& out) {
324 return ReadRepeatedVarintField<int64_t>(out, internal::VarintType::kZigZag);
325 }
326
327 // Reads a proto bool value from the current position.
328 Result<bool> ReadBool() {
329 return ReadVarintField<bool>(internal::VarintType::kUnsigned);
330 }
331
332 // Reads repeated bool values from the current position using packed
333 // encoding.
334 //
335 // Returns the number of values read. In the case of error, the return value
336 // indicates the number of values successfully read, in addition to the
337 // error.
338 StatusWithSize ReadPackedBool(span<bool> out) {
339 return ReadPackedVarintField(
340 as_writable_bytes(out), sizeof(bool), internal::VarintType::kUnsigned);
341 }
342
343 // Reads repeated bool values from the current position into the vector,
344 // supporting either repeated single field elements or packed encoding.
345 Status ReadRepeatedBool(pw::Vector<bool>& out) {
346 return ReadRepeatedVarintField<bool>(out, internal::VarintType::kUnsigned);
347 }
348
349 // Reads a proto fixed32 value from the current position.
350 Result<uint32_t> ReadFixed32() { return ReadFixedField<uint32_t>(); }
351
352 // Reads repeated fixed32 values from the current position using packed
353 // encoding.
354 //
355 // Returns the number of values read.
356 StatusWithSize ReadPackedFixed32(span<uint32_t> out) {
357 return ReadPackedFixedField(as_writable_bytes(out), sizeof(uint32_t));
358 }
359
360 // Reads repeated fixed32 values from the current position into the vector,
361 // supporting either repeated single field elements or packed encoding.
362 Status ReadRepeatedFixed32(pw::Vector<uint32_t>& out) {
363 return ReadRepeatedFixedField<uint32_t>(out);
364 }
365
366 // Reads a proto fixed64 value from the current position.
367 Result<uint64_t> ReadFixed64() { return ReadFixedField<uint64_t>(); }
368
369 // Reads repeated fixed64 values from the current position using packed
370 // encoding.
371 //
372 // Returns the number of values read.
373 StatusWithSize ReadPackedFixed64(span<uint64_t> out) {
374 return ReadPackedFixedField(as_writable_bytes(out), sizeof(uint64_t));
375 }
376
377 // Reads repeated fixed64 values from the current position into the vector,
378 // supporting either repeated single field elements or packed encoding.
379 Status ReadRepeatedFixed64(pw::Vector<uint64_t>& out) {
380 return ReadRepeatedFixedField<uint64_t>(out);
381 }
382
383 // Reads a proto sfixed32 value from the current position.
384 Result<int32_t> ReadSfixed32() { return ReadFixedField<int32_t>(); }
385
386 // Reads repeated sfixed32 values from the current position using packed
387 // encoding.
388 //
389 // Returns the number of values read.
390 StatusWithSize ReadPackedSfixed32(span<int32_t> out) {
391 return ReadPackedFixedField(as_writable_bytes(out), sizeof(int32_t));
392 }
393
394 // Reads repeated sfixed32 values from the current position into the vector,
395 // supporting either repeated single field elements or packed encoding.
396 Status ReadRepeatedSfixed32(pw::Vector<int32_t>& out) {
397 return ReadRepeatedFixedField<int32_t>(out);
398 }
399
400 // Reads a proto sfixed64 value from the current position.
401 Result<int64_t> ReadSfixed64() { return ReadFixedField<int64_t>(); }
402
403 // Reads repeated sfixed64 values from the current position using packed
404 // encoding.
405 //
406 // Returns the number of values read.
407 StatusWithSize ReadPackedSfixed64(span<int64_t> out) {
408 return ReadPackedFixedField(as_writable_bytes(out), sizeof(int64_t));
409 }
410
411 // Reads repeated sfixed64 values from the current position into the vector,
412 // supporting either repeated single field elements or packed encoding.
413 Status ReadRepeatedSfixed64(pw::Vector<int64_t>& out) {
414 return ReadRepeatedFixedField<int64_t>(out);
415 }
416
417 // Reads a proto float value from the current position.
418 Result<float> ReadFloat() {
419 static_assert(sizeof(float) == sizeof(uint32_t),
420 "Float and uint32_t must be the same size for protobufs");
421 return ReadFixedField<float>();
422 }
423
424 // Reads repeated float values from the current position using packed
425 // encoding.
426 //
427 // Returns the number of values read.
428 StatusWithSize ReadPackedFloat(span<float> out) {
429 static_assert(sizeof(float) == sizeof(uint32_t),
430 "Float and uint32_t must be the same size for protobufs");
431 return ReadPackedFixedField(as_writable_bytes(out), sizeof(float));
432 }
433
434 // Reads repeated float values from the current position into the vector,
435 // supporting either repeated single field elements or packed encoding.
436 Status ReadRepeatedFloat(pw::Vector<float>& out) {
437 return ReadRepeatedFixedField<float>(out);
438 }
439
440 // Reads a proto double value from the current position.
441 Result<double> ReadDouble() {
442 static_assert(sizeof(double) == sizeof(uint64_t),
443 "Double and uint64_t must be the same size for protobufs");
444 return ReadFixedField<double>();
445 }
446
447 // Reads repeated double values from the current position using packed
448 // encoding.
449 //
450 // Returns the number of values read.
451 StatusWithSize ReadPackedDouble(span<double> out) {
452 static_assert(sizeof(double) == sizeof(uint64_t),
453 "Double and uint64_t must be the same size for protobufs");
454 return ReadPackedFixedField(as_writable_bytes(out), sizeof(double));
455 }
456
457 // Reads repeated double values from the current position into the vector,
458 // supporting either repeated single field elements or packed encoding.
459 Status ReadRepeatedDouble(pw::Vector<double>& out) {
460 return ReadRepeatedFixedField<double>(out);
461 }
462
463 // Reads a proto string value from the current position. The string is
464 // copied into the provided buffer and the read size is returned. The copied
465 // string will NOT be null terminated; this should be done manually if
466 // desired.
467 //
468 // If the buffer is too small to fit the string value, RESOURCE_EXHAUSTED is
469 // returned and no data is read. The decoder's position remains on the
470 // string field.
471 StatusWithSize ReadString(span<char> out) {
472 return ReadBytes(as_writable_bytes(out));
473 }
474
475 // Reads a proto bytes value from the current position. The value is copied
476 // into the provided buffer and the read size is returned.
477 //
478 // If the buffer is too small to fit the bytes value, RESOURCE_EXHAUSTED is
479 // returned and no data is read. The decoder's position remains on the bytes
480 // field.
481 //
482 // For larger bytes values that won't fit into memory, use GetBytesReader()
483 // to acquire a stream::Reader to the bytes instead.
484 StatusWithSize ReadBytes(span<std::byte> out) {
485 return ReadDelimitedField(out);
486 }
487
488 // Returns a stream::Reader to a bytes (or string) field at the current
489 // position in the protobuf.
490 //
491 // The BytesReader shares the same stream as the decoder, using RAII to manage
492 // ownership of the stream. The decoder cannot be used while the BytesStream
493 // is alive.
494 //
495 // StreamDecoder decoder(my_stream);
496 //
497 // while (decoder.Next().ok()) {
498 // switch (decoder.FieldNumber()) {
499 //
500 // // Bytes field.
501 // case 1: {
502 // // The BytesReader is created within a new C++ scope. While it is
503 // // alive, the decoder cannot be used.
504 // StreamDecoder::BytesReader reader = decoder.GetBytesReader();
505 //
506 // // Do stuff with the reader.
507 // reader.Read(&some_buffer);
508 //
509 // // At the end of the scope, the reader is destructed and the
510 // // decoder becomes usable again.
511 // break;
512 // }
513 // }
514 // }
515 //
516 // The returned decoder is seekable if the stream's decoder is seekable.
517 BytesReader GetBytesReader();
518
519 // Returns a decoder to a nested protobuf message located at the current
520 // position.
521 //
522 // The nested decoder shares the same stream as its parent, using RAII to
523 // manage ownership of the stream. The parent decoder cannot be used while the
524 // nested one is alive.
525 //
526 // See the example in GetBytesReader() above for RAII semantics and usage.
527 StreamDecoder GetNestedDecoder();
528
529 struct Bounds {
530 size_t low;
531 size_t high;
532 };
533
534 // Get the interval of the payload part of a length-delimited field. That is,
535 // the interval exluding the field key and the length prefix. The bounds are
536 // relative to the given reader.
537 Result<Bounds> GetLengthDelimitedPayloadBounds();
538
539 protected:
540 // Specialized move constructor used only for codegen.
541 //
542 // Postcondition: The other decoder is invalidated and cannot be used as it
543 // acts like a parent decoder with an active child decoder.
544 constexpr StreamDecoder(StreamDecoder&& other)
545 : reader_(other.reader_),
546 stream_bounds_(other.stream_bounds_),
547 position_(other.position_),
548 current_field_(other.current_field_),
549 delimited_field_size_(other.delimited_field_size_),
550 delimited_field_offset_(other.delimited_field_offset_),
551 parent_(other.parent_),
552 field_consumed_(other.field_consumed_),
553 nested_reader_open_(other.nested_reader_open_),
554 status_(other.status_) {
555 PW_ASSERT(!nested_reader_open_);
556 // Make the nested decoder look like it has an open child to block reads for
557 // the remainder of the object's life, and an invalid status to ensure it
558 // doesn't advance the stream on destruction.
559 other.nested_reader_open_ = true;
560 other.parent_ = nullptr;
561 other.status_ = pw::Status::Cancelled();
562 }
563
564 // Reads proto values from the stream and decodes them into the structure
565 // contained within message according to the description of fields in table.
566 //
567 // This is called by codegen subclass Read() functions that accept a typed
568 // struct Message reference, using the appropriate codegen MessageField table
569 // corresponding to that type.
570 Status Read(span<std::byte> message,
572
573 private:
574 friend class BytesReader;
575
576 // The FieldKey class can't store an invalid key, so pick a random large key
577 // to set as the initial value. This will be overwritten the first time Next()
578 // is called, and FieldKey() fails if Next() is not called first -- ensuring
579 // that users will never see this value.
580 static constexpr FieldKey kInitialFieldKey =
581 FieldKey(20000, WireType::kVarint);
582
583 constexpr StreamDecoder(stream::Reader& reader,
584 StreamDecoder* parent,
585 size_t low,
586 size_t high)
587 : reader_(reader),
588 stream_bounds_({low, high}),
589 position_(parent->position_),
590 current_field_(kInitialFieldKey),
591 delimited_field_size_(0),
592 delimited_field_offset_(0),
593 parent_(parent),
594 field_consumed_(true),
595 nested_reader_open_(false),
596 status_(OkStatus()) {}
597
598 // Creates an unusable decoder in an error state. This is required as
599 // GetNestedEncoder does not have a way to report an error in its API.
600 constexpr StreamDecoder(stream::Reader& reader,
601 StreamDecoder* parent,
602 Status status)
603 : reader_(reader),
604 stream_bounds_({0, std::numeric_limits<size_t>::max()}),
605 position_(0),
606 current_field_(kInitialFieldKey),
607 delimited_field_size_(0),
608 delimited_field_offset_(0),
609 parent_(parent),
610 field_consumed_(true),
611 nested_reader_open_(false),
612 status_(status) {
613 PW_ASSERT(!status.ok());
614 }
615
616 Status Advance(size_t end_position);
617
618 size_t RemainingBytes() {
619 return stream_bounds_.high < std::numeric_limits<size_t>::max()
620 ? stream_bounds_.high - position_
621 : std::numeric_limits<size_t>::max();
622 }
623
624 void CloseBytesReader(BytesReader& reader);
625 void CloseNestedDecoder(StreamDecoder& nested);
626
627 Status ReadFieldKey();
628 Status SkipField();
629
630 Status ReadVarintField(span<std::byte> out, internal::VarintType decode_type);
631
632 StatusWithSize ReadOneVarint(span<std::byte> out,
633 internal::VarintType decode_type);
634
635 template <typename T>
636 Result<T> ReadVarintField(internal::VarintType decode_type) {
637 static_assert(
638 std::is_same_v<T, bool> || std::is_same_v<T, uint32_t> ||
639 std::is_same_v<T, int32_t> || std::is_same_v<T, uint64_t> ||
640 std::is_same_v<T, int64_t>,
641 "Protobuf varints must be of type bool, uint32_t, int32_t, uint64_t, "
642 "or int64_t");
643 using DecodedValue =
644 std::conditional_t<std::is_signed<T>::value, int64_t, uint64_t>;
645 static_assert(sizeof(DecodedValue) >= sizeof(T));
646
647 DecodedValue result;
648 if (Status status =
649 ReadVarintField(as_writable_bytes(span(&result, 1)), decode_type);
650 !status.ok()) {
651 return status;
652 }
653 if (result > static_cast<DecodedValue>(std::numeric_limits<T>::max()) ||
654 result < static_cast<DecodedValue>(std::numeric_limits<T>::lowest())) {
655 // When a varint is too big to fit in an integer, the decoder returns
656 // FAILED_PRECONDITION, so this mirrors that behavior.
658 }
659 return static_cast<T>(result);
660 }
661
662 Status ReadFixedField(span<std::byte> out);
663
664 template <typename T>
665 Result<T> ReadFixedField() {
666 static_assert(
667 sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t),
668 "Protobuf fixed-size fields must be 32- or 64-bit");
669
670 T result;
671 if (Status status = ReadFixedField(as_writable_bytes(span(&result, 1)));
672 !status.ok()) {
673 return status;
674 }
675
676 return result;
677 }
678
679 StatusWithSize ReadDelimitedField(span<std::byte> out);
680
681 StatusWithSize ReadPackedFixedField(span<std::byte> out, size_t elem_size);
682
683 StatusWithSize ReadPackedVarintField(span<std::byte> out,
684 size_t elem_size,
685 internal::VarintType decode_type);
686
687 template <typename T>
688 Status ReadRepeatedFixedField(pw::Vector<T>& out) {
689 static_assert(
690 sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
691 "Unsupported element size");
692 if (out.full()) {
694 }
695 const size_t old_size = out.size();
696 out.resize(out.capacity());
697 size_t size = old_size;
698 Status status =
699 ReadRepeatedFixedFieldGeneric(reinterpret_cast<std::byte*>(out.data()),
700 out.capacity(),
701 size,
702 sizeof(T));
703 out.resize(size);
704 return status;
705 }
706
707 template <typename T>
708 Status ReadRepeatedVarintField(pw::Vector<T>& out,
709 internal::VarintType decode_type) {
710 static_assert(
711 sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
712 "Unsupported element size");
713 if (out.full()) {
715 }
716 const size_t old_size = out.size();
717 out.resize(out.capacity());
718 size_t size = old_size;
719 Status status =
720 ReadRepeatedVarintFieldGeneric(reinterpret_cast<std::byte*>(out.data()),
721 out.capacity(),
722 size,
723 sizeof(T),
724 decode_type);
725 out.resize(size);
726 return status;
727 }
728
729 // Reads one varint field for each element in the repeated field, with a
730 // runtime size to avoid instantiating the function multiple times. The size
731 // is passed as its base 2 log to avoid repeated multiplications in the impl
732 // (bit shift instead of multiply).
733 Status ReadRepeatedVarintFieldGeneric(std::byte* data,
734 size_t capacity,
735 size_t& size,
736 size_t elem_size,
737 internal::VarintType decode_type);
738
739 Status ReadRepeatedFixedFieldGeneric(std::byte* data,
740 size_t capacity,
741 size_t& size,
742 size_t elem_size);
743
744 template <typename Container>
745 Status ReadStringOrBytesField(std::byte* raw_container) {
746 auto& container = *reinterpret_cast<Container*>(raw_container);
747 if (container.capacity() < delimited_field_size_) {
749 }
750 container.resize(container.capacity());
751 const auto sws = ReadDelimitedField(as_writable_bytes(span(container)));
752 size_t size = sws.size();
753 PW_DASSERT(size <= std::numeric_limits<uint16_t>::max());
754 container.resize(static_cast<uint16_t>(size));
755 return sws.status();
756 }
757
758 Status CheckOkToRead(WireType type);
759
760 stream::Reader& reader_;
761 Bounds stream_bounds_;
762 size_t position_;
763
764 FieldKey current_field_;
765 size_t delimited_field_size_;
766 size_t delimited_field_offset_;
767
768 StreamDecoder* parent_;
769
770 bool field_consumed_;
771 bool nested_reader_open_;
772
773 Status status_;
774
775 friend class Message;
776};
777
779
780} // namespace pw::protobuf
Definition: result.h:145
Definition: status.h:120
static constexpr Status Cancelled()
Definition: status.h:139
constexpr bool ok() const
Definition: status.h:346
static constexpr Status FailedPrecondition()
Definition: status.h:243
static constexpr Status ResourceExhausted()
Definition: status.h:230
Definition: status_with_size.h:51
Definition: vector.h:66
Definition: wire_format.h:54
Definition: stream_decoder.h:75
Status DoSeek(ptrdiff_t offset, Whence origin) final
Virtual Seek() function implemented by derived classes.
StatusWithSize DoRead(ByteSpan destination) final
Virtual Read() function implemented by derived classes.
Definition: stream_decoder.h:68
Definition: stream.h:326
Definition: stream.h:354
Whence
Positions from which to seek.
Definition: stream.h:48
constexpr Status OkStatus()
Definition: status.h:450
Definition: stream_decoder.h:529