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