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