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