xref: /aosp_15_r20/external/pigweed/pw_protobuf/stream_decoder.cc (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 
15 #include "pw_protobuf/stream_decoder.h"
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <cstring>
20 #include <limits>
21 #include <optional>
22 
23 #include "pw_assert/assert.h"
24 #include "pw_assert/check.h"
25 #include "pw_bytes/bit.h"
26 #include "pw_containers/vector.h"
27 #include "pw_function/function.h"
28 #include "pw_protobuf/encoder.h"
29 #include "pw_protobuf/internal/codegen.h"
30 #include "pw_protobuf/wire_format.h"
31 #include "pw_span/span.h"
32 #include "pw_status/status.h"
33 #include "pw_status/status_with_size.h"
34 #include "pw_status/try.h"
35 #include "pw_string/string.h"
36 #include "pw_varint/stream.h"
37 #include "pw_varint/varint.h"
38 
39 namespace pw::protobuf {
40 
41 using internal::VarintType;
42 
DoSeek(ptrdiff_t offset,Whence origin)43 Status StreamDecoder::BytesReader::DoSeek(ptrdiff_t offset, Whence origin) {
44   PW_TRY(status_);
45   if (!decoder_.reader_.seekable()) {
46     return Status::Unimplemented();
47   }
48 
49   ptrdiff_t absolute_position = std::numeric_limits<ptrdiff_t>::min();
50 
51   // Convert from the position within the bytes field to the position within the
52   // proto stream.
53   switch (origin) {
54     case Whence::kBeginning:
55       absolute_position = start_offset_ + offset;
56       break;
57 
58     case Whence::kCurrent:
59       absolute_position = decoder_.position_ + offset;
60       break;
61 
62     case Whence::kEnd:
63       absolute_position = end_offset_ + offset;
64       break;
65   }
66 
67   if (absolute_position < 0) {
68     return Status::InvalidArgument();
69   }
70 
71   if (static_cast<size_t>(absolute_position) < start_offset_ ||
72       static_cast<size_t>(absolute_position) > end_offset_) {
73     return Status::OutOfRange();
74   }
75 
76   PW_TRY(decoder_.reader_.Seek(absolute_position, Whence::kBeginning));
77   decoder_.position_ = absolute_position;
78   return OkStatus();
79 }
80 
DoRead(ByteSpan destination)81 StatusWithSize StreamDecoder::BytesReader::DoRead(ByteSpan destination) {
82   if (!status_.ok()) {
83     return StatusWithSize(status_, 0);
84   }
85 
86   if (decoder_.position_ >= end_offset_ || decoder_.position_ < start_offset_) {
87     return StatusWithSize::OutOfRange();
88   }
89 
90   // Bound the read buffer to the size of the bytes field.
91   size_t max_length = end_offset_ - decoder_.position_;
92   if (destination.size() > max_length) {
93     destination = destination.first(max_length);
94   }
95 
96   Result<ByteSpan> result = decoder_.reader_.Read(destination);
97   if (!result.ok()) {
98     return StatusWithSize(result.status(), 0);
99   }
100 
101   decoder_.position_ += result.value().size();
102   return StatusWithSize(result.value().size());
103 }
104 
~StreamDecoder()105 StreamDecoder::~StreamDecoder() {
106   if (parent_ != nullptr) {
107     parent_->CloseNestedDecoder(*this);
108   } else if (stream_bounds_.high < std::numeric_limits<size_t>::max()) {
109     if (status_.ok()) {
110       // Advance the stream to the end of the bounds.
111       PW_CHECK(Advance(stream_bounds_.high).ok());
112     }
113   }
114 }
115 
Next()116 Status StreamDecoder::Next() {
117   PW_CHECK(!nested_reader_open_,
118            "Cannot use parent decoder while a nested one is open");
119 
120   PW_TRY(status_);
121 
122   if (!field_consumed_) {
123     PW_TRY(SkipField());
124   }
125 
126   if (position_ >= stream_bounds_.high) {
127     return Status::OutOfRange();
128   }
129 
130   status_ = ReadFieldKey();
131   return status_;
132 }
133 
GetBytesReader()134 StreamDecoder::BytesReader StreamDecoder::GetBytesReader() {
135   Status status = CheckOkToRead(WireType::kDelimited);
136 
137   if (reader_.ConservativeReadLimit() < delimited_field_size_) {
138     status.Update(Status::DataLoss());
139   }
140 
141   nested_reader_open_ = true;
142 
143   if (!status.ok()) {
144     return BytesReader(*this, status);
145   }
146 
147   size_t low = position_;
148   size_t high = low + delimited_field_size_;
149 
150   return BytesReader(*this, low, high);
151 }
152 
GetNestedDecoder()153 StreamDecoder StreamDecoder::GetNestedDecoder() {
154   Status status = CheckOkToRead(WireType::kDelimited);
155 
156   if (reader_.ConservativeReadLimit() < delimited_field_size_) {
157     status.Update(Status::DataLoss());
158   }
159 
160   nested_reader_open_ = true;
161 
162   if (!status.ok()) {
163     return StreamDecoder(reader_, this, status);
164   }
165 
166   size_t low = position_;
167   size_t high = low + delimited_field_size_;
168 
169   return StreamDecoder(reader_, this, low, high);
170 }
171 
Advance(size_t end_position)172 Status StreamDecoder::Advance(size_t end_position) {
173   if (reader_.seekable()) {
174     PW_TRY(reader_.Seek(end_position - position_, stream::Stream::kCurrent));
175     position_ = end_position;
176     return OkStatus();
177   }
178 
179   while (position_ < end_position) {
180     std::byte b;
181     PW_TRY(reader_.Read(span(&b, 1)));
182     position_++;
183   }
184   return OkStatus();
185 }
186 
CloseBytesReader(BytesReader & reader)187 void StreamDecoder::CloseBytesReader(BytesReader& reader) {
188   status_ = reader.status_;
189   if (status_.ok()) {
190     // Advance the stream to the end of the bytes field.
191     // The BytesReader already updated our position_ field as bytes were read.
192     PW_CHECK(Advance(reader.end_offset_).ok());
193   }
194 
195   field_consumed_ = true;
196   nested_reader_open_ = false;
197 }
198 
CloseNestedDecoder(StreamDecoder & nested)199 void StreamDecoder::CloseNestedDecoder(StreamDecoder& nested) {
200   PW_CHECK_PTR_EQ(nested.parent_, this);
201 
202   nested.nested_reader_open_ = true;
203   nested.parent_ = nullptr;
204 
205   status_ = nested.status_;
206   position_ = nested.position_;
207   if (status_.ok()) {
208     // Advance the stream to the end of the nested message field.
209     PW_CHECK(Advance(nested.stream_bounds_.high).ok());
210   }
211 
212   field_consumed_ = true;
213   nested_reader_open_ = false;
214 }
215 
ReadFieldKey()216 Status StreamDecoder::ReadFieldKey() {
217   PW_DCHECK(field_consumed_);
218 
219   uint64_t varint = 0;
220   PW_TRY_ASSIGN(size_t bytes_read,
221                 varint::Read(reader_, &varint, RemainingBytes()));
222   position_ += bytes_read;
223 
224   if (!FieldKey::IsValidKey(varint)) {
225     return Status::DataLoss();
226   }
227 
228   PW_DCHECK(varint <= std::numeric_limits<uint32_t>::max());
229   current_field_ = FieldKey(static_cast<uint32_t>(varint));
230 
231   if (current_field_.wire_type() == WireType::kDelimited) {
232     // Read the length varint of length-delimited fields immediately to simplify
233     // later processing of the field.
234     StatusWithSize sws = varint::Read(reader_, &varint, RemainingBytes());
235     position_ += sws.size();
236     if (sws.IsOutOfRange()) {
237       // Out of range indicates the end of the stream. As a value is expected
238       // here, report it as a data loss and terminate the decode operation.
239       return Status::DataLoss();
240     }
241     if (!sws.ok()) {
242       return sws.status();
243     }
244 
245     if (varint > std::numeric_limits<uint32_t>::max()) {
246       return Status::DataLoss();
247     }
248 
249     delimited_field_size_ = varint;
250     delimited_field_offset_ = position_;
251   }
252 
253   field_consumed_ = false;
254   return OkStatus();
255 }
256 
GetLengthDelimitedPayloadBounds()257 Result<StreamDecoder::Bounds> StreamDecoder::GetLengthDelimitedPayloadBounds() {
258   PW_TRY(CheckOkToRead(WireType::kDelimited));
259   return StreamDecoder::Bounds{delimited_field_offset_,
260                                delimited_field_size_ + delimited_field_offset_};
261 }
262 
263 // Consumes the current protobuf field, advancing the stream to the key of the
264 // next field (if one exists).
SkipField()265 Status StreamDecoder::SkipField() {
266   PW_DCHECK(!field_consumed_);
267 
268   size_t bytes_to_skip = 0;
269   uint64_t value = 0;
270 
271   switch (current_field_.wire_type()) {
272     case WireType::kVarint: {
273       // Consume the varint field; nothing more to skip afterward.
274       PW_TRY_ASSIGN(size_t bytes_read,
275                     varint::Read(reader_, &value, RemainingBytes()));
276       position_ += bytes_read;
277       break;
278     }
279     case WireType::kDelimited:
280       bytes_to_skip = delimited_field_size_;
281       break;
282 
283     case WireType::kFixed32:
284       bytes_to_skip = sizeof(uint32_t);
285       break;
286 
287     case WireType::kFixed64:
288       bytes_to_skip = sizeof(uint64_t);
289       break;
290   }
291 
292   if (bytes_to_skip > 0) {
293     // Check if the stream has the field available. If not, report it as a
294     // DATA_LOSS since the proto is invalid (as opposed to OUT_OF_BOUNDS if we
295     // just tried to seek beyond the end).
296     if (reader_.ConservativeReadLimit() < bytes_to_skip) {
297       status_ = Status::DataLoss();
298       return status_;
299     }
300 
301     if (RemainingBytes() < bytes_to_skip) {
302       status_ = Status::DataLoss();
303       return status_;
304     }
305 
306     PW_TRY(Advance(position_ + bytes_to_skip));
307   }
308 
309   field_consumed_ = true;
310   return OkStatus();
311 }
312 
ReadVarintField(span<std::byte> out,VarintType decode_type)313 Status StreamDecoder::ReadVarintField(span<std::byte> out,
314                                       VarintType decode_type) {
315   PW_CHECK(out.size() == sizeof(bool) || out.size() == sizeof(uint32_t) ||
316                out.size() == sizeof(uint64_t),
317            "Protobuf varints must only be used with bool, int32_t, uint32_t, "
318            "int64_t, or uint64_t");
319   PW_TRY(CheckOkToRead(WireType::kVarint));
320 
321   const StatusWithSize sws = ReadOneVarint(out, decode_type);
322   if (sws.status() != Status::DataLoss())
323     field_consumed_ = true;
324   return sws.status();
325 }
326 
ReadOneVarint(span<std::byte> out,VarintType decode_type)327 StatusWithSize StreamDecoder::ReadOneVarint(span<std::byte> out,
328                                             VarintType decode_type) {
329   uint64_t value;
330   StatusWithSize sws = varint::Read(reader_, &value, RemainingBytes());
331   position_ += sws.size();
332   if (sws.IsOutOfRange()) {
333     // Out of range indicates the end of the stream. As a value is expected
334     // here, report it as a data loss and terminate the decode operation.
335     status_ = Status::DataLoss();
336     return StatusWithSize(status_, sws.size());
337   }
338   if (!sws.ok()) {
339     return sws;
340   }
341 
342   if (out.size() == sizeof(uint64_t)) {
343     if (decode_type == VarintType::kUnsigned) {
344       std::memcpy(out.data(), &value, out.size());
345     } else {
346       const int64_t signed_value = decode_type == VarintType::kZigZag
347                                        ? varint::ZigZagDecode(value)
348                                        : static_cast<int64_t>(value);
349       std::memcpy(out.data(), &signed_value, out.size());
350     }
351   } else if (out.size() == sizeof(uint32_t)) {
352     if (decode_type == VarintType::kUnsigned) {
353       if (value > std::numeric_limits<uint32_t>::max()) {
354         return StatusWithSize(Status::FailedPrecondition(), sws.size());
355       }
356       std::memcpy(out.data(), &value, out.size());
357     } else {
358       const int64_t signed_value = decode_type == VarintType::kZigZag
359                                        ? varint::ZigZagDecode(value)
360                                        : static_cast<int64_t>(value);
361       if (signed_value > std::numeric_limits<int32_t>::max() ||
362           signed_value < std::numeric_limits<int32_t>::min()) {
363         return StatusWithSize(Status::FailedPrecondition(), sws.size());
364       }
365       std::memcpy(out.data(), &signed_value, out.size());
366     }
367   } else if (out.size() == sizeof(bool)) {
368     PW_CHECK(decode_type == VarintType::kUnsigned,
369              "Protobuf bool can never be signed");
370     std::memcpy(out.data(), &value, out.size());
371   }
372 
373   return sws;
374 }
375 
ReadFixedField(span<std::byte> out)376 Status StreamDecoder::ReadFixedField(span<std::byte> out) {
377   WireType expected_wire_type =
378       out.size() == sizeof(uint32_t) ? WireType::kFixed32 : WireType::kFixed64;
379   PW_TRY(CheckOkToRead(expected_wire_type));
380 
381   if (reader_.ConservativeReadLimit() < out.size()) {
382     status_ = Status::DataLoss();
383     return status_;
384   }
385 
386   if (RemainingBytes() < out.size()) {
387     status_ = Status::DataLoss();
388     return status_;
389   }
390 
391   PW_TRY(reader_.Read(out));
392   position_ += out.size();
393   field_consumed_ = true;
394 
395   if (endian::native != endian::little) {
396     std::reverse(out.begin(), out.end());
397   }
398 
399   return OkStatus();
400 }
401 
ReadDelimitedField(span<std::byte> out)402 StatusWithSize StreamDecoder::ReadDelimitedField(span<std::byte> out) {
403   if (Status status = CheckOkToRead(WireType::kDelimited); !status.ok()) {
404     return StatusWithSize(status, 0);
405   }
406 
407   if (reader_.ConservativeReadLimit() < delimited_field_size_) {
408     status_ = Status::DataLoss();
409     return StatusWithSize(status_, 0);
410   }
411 
412   if (out.size() < delimited_field_size_) {
413     // Value can't fit into the provided buffer. Don't advance the cursor so
414     // that the field can be re-read with a larger buffer or through the stream
415     // API.
416     return StatusWithSize::ResourceExhausted();
417   }
418 
419   Result<ByteSpan> result = reader_.Read(out.first(delimited_field_size_));
420   if (!result.ok()) {
421     return StatusWithSize(result.status(), 0);
422   }
423 
424   position_ += result.value().size();
425   field_consumed_ = true;
426   return StatusWithSize(result.value().size());
427 }
428 
ReadPackedFixedField(span<std::byte> out,size_t elem_size)429 StatusWithSize StreamDecoder::ReadPackedFixedField(span<std::byte> out,
430                                                    size_t elem_size) {
431   if (Status status = CheckOkToRead(WireType::kDelimited); !status.ok()) {
432     return StatusWithSize(status, 0);
433   }
434 
435   if (reader_.ConservativeReadLimit() < delimited_field_size_) {
436     status_ = Status::DataLoss();
437     return StatusWithSize(status_, 0);
438   }
439 
440   if (out.size() < delimited_field_size_) {
441     // Value can't fit into the provided buffer. Don't advance the cursor so
442     // that the field can be re-read with a larger buffer or through the stream
443     // API.
444     return StatusWithSize::ResourceExhausted();
445   }
446 
447   Result<ByteSpan> result = reader_.Read(out.first(delimited_field_size_));
448   if (!result.ok()) {
449     return StatusWithSize(result.status(), 0);
450   }
451 
452   position_ += result.value().size();
453   field_consumed_ = true;
454 
455   // Decode little-endian serialized packed fields.
456   if (endian::native != endian::little) {
457     for (auto out_start = out.begin(); out_start != out.end();
458          out_start += elem_size) {
459       std::reverse(out_start, out_start + elem_size);
460     }
461   }
462 
463   return StatusWithSize(result.value().size() / elem_size);
464 }
465 
ReadPackedVarintField(span<std::byte> out,size_t elem_size,VarintType decode_type)466 StatusWithSize StreamDecoder::ReadPackedVarintField(span<std::byte> out,
467                                                     size_t elem_size,
468                                                     VarintType decode_type) {
469   PW_CHECK(elem_size == sizeof(bool) || elem_size == sizeof(uint32_t) ||
470                elem_size == sizeof(uint64_t),
471            "Protobuf varints must only be used with bool, int32_t, uint32_t, "
472            "int64_t, or uint64_t");
473 
474   if (Status status = CheckOkToRead(WireType::kDelimited); !status.ok()) {
475     return StatusWithSize(status, 0);
476   }
477 
478   if (reader_.ConservativeReadLimit() < delimited_field_size_) {
479     status_ = Status::DataLoss();
480     return StatusWithSize(status_, 0);
481   }
482 
483   size_t bytes_read = 0;
484   size_t number_out = 0;
485   while (bytes_read < delimited_field_size_ && !out.empty()) {
486     const StatusWithSize sws = ReadOneVarint(out.first(elem_size), decode_type);
487     if (!sws.ok()) {
488       return StatusWithSize(sws.status(), number_out);
489     }
490 
491     bytes_read += sws.size();
492     out = out.subspan(elem_size);
493     ++number_out;
494   }
495 
496   if (bytes_read < delimited_field_size_) {
497     return StatusWithSize(Status::ResourceExhausted(), number_out);
498   }
499 
500   field_consumed_ = true;
501   return StatusWithSize(OkStatus(), number_out);
502 }
503 
CheckOkToRead(WireType type)504 Status StreamDecoder::CheckOkToRead(WireType type) {
505   PW_CHECK(!nested_reader_open_,
506            "Cannot read from a decoder while a nested decoder is open");
507   PW_CHECK(!field_consumed_,
508            "Attempting to read from protobuf decoder without first calling "
509            "Next()");
510 
511   // Attempting to read the wrong type is typically a programmer error;
512   // however, it could also occur due to data corruption. As we don't want to
513   // crash on bad data, return NOT_FOUND here to distinguish it from other
514   // corruption cases.
515   if (current_field_.wire_type() != type) {
516     status_ = Status::NotFound();
517   }
518 
519   return status_;
520 }
521 
Read(span<std::byte> message,span<const internal::MessageField> table)522 Status StreamDecoder::Read(span<std::byte> message,
523                            span<const internal::MessageField> table) {
524   PW_TRY(status_);
525 
526   while (Next().ok()) {
527     // Find the field in the table,
528     // TODO: b/234876102 - Finding the field can be made more efficient.
529     const auto field =
530         std::find(table.begin(), table.end(), current_field_.field_number());
531     if (field == table.end()) {
532       // If the field is not found, skip to the next one.
533       // TODO: b/234873295 - Provide a way to allow the caller to inspect
534       // unknown fields, and serialize them back out later.
535       continue;
536     }
537 
538     // Calculate the span of bytes corresponding to the structure field to
539     // output into.
540     const auto out =
541         message.subspan(field->field_offset(), field->field_size());
542     PW_CHECK(out.begin() >= message.begin() && out.end() <= message.end());
543 
544     // If the field is using callbacks, interpret the output field accordingly
545     // and allow the caller to provide custom handling.
546     if (field->callback_type() == internal::CallbackType::kSingleField) {
547       const Callback<StreamEncoder, StreamDecoder>* callback =
548           reinterpret_cast<const Callback<StreamEncoder, StreamDecoder>*>(
549               out.data());
550       PW_TRY(callback->Decode(*this));
551       continue;
552     }
553     if (field->callback_type() == internal::CallbackType::kOneOfGroup) {
554       const OneOf<StreamEncoder, StreamDecoder>* callback =
555           reinterpret_cast<const OneOf<StreamEncoder, StreamDecoder>*>(
556               out.data());
557       PW_TRY(callback->Decode(
558           static_cast<NullFields>(current_field_.field_number()), *this));
559       continue;
560     }
561 
562     // Switch on the expected wire type of the field, not the actual, to ensure
563     // the remote encoder doesn't influence our decoding unexpectedly.
564     switch (field->wire_type()) {
565       case WireType::kFixed64:
566       case WireType::kFixed32: {
567         // Fixed fields call ReadFixedField() for singular case, and either
568         // ReadPackedFixedField() or ReadRepeatedFixedField() for repeated
569         // fields.
570         PW_CHECK(field->elem_size() == (field->wire_type() == WireType::kFixed32
571                                             ? sizeof(uint32_t)
572                                             : sizeof(uint64_t)),
573                  "Mismatched message field type and size");
574         if (field->is_fixed_size()) {
575           PW_CHECK(field->is_repeated(), "Non-repeated fixed size field");
576           PW_TRY(ReadPackedFixedField(out, field->elem_size()));
577         } else if (field->is_repeated()) {
578           // The struct member for this field is a vector of a type
579           // corresponding to the field element size. Cast to the correct
580           // vector type so we're not performing type aliasing (except for
581           // unsigned vs signed which is explicitly allowed).
582           if (field->elem_size() == sizeof(uint64_t)) {
583             auto* vector = reinterpret_cast<pw::Vector<uint64_t>*>(out.data());
584             PW_TRY(ReadRepeatedFixedField(*vector));
585           } else if (field->elem_size() == sizeof(uint32_t)) {
586             auto* vector = reinterpret_cast<pw::Vector<uint32_t>*>(out.data());
587             PW_TRY(ReadRepeatedFixedField(*vector));
588           }
589         } else if (field->is_optional()) {
590           // The struct member for this field is a std::optional of a type
591           // corresponding to the field element size. Cast to the correct
592           // optional type so we're not performing type aliasing (except for
593           // unsigned vs signed which is explicitly allowed), and assign through
594           // a temporary.
595           if (field->elem_size() == sizeof(uint64_t)) {
596             uint64_t value = 0;
597             PW_TRY(ReadFixedField(as_writable_bytes(span(&value, 1))));
598             auto* optional =
599                 reinterpret_cast<std::optional<uint64_t>*>(out.data());
600             *optional = value;
601           } else if (field->elem_size() == sizeof(uint32_t)) {
602             uint32_t value = 0;
603             PW_TRY(ReadFixedField(as_writable_bytes(span(&value, 1))));
604             auto* optional =
605                 reinterpret_cast<std::optional<uint32_t>*>(out.data());
606             *optional = value;
607           }
608         } else {
609           PW_CHECK(out.size() == field->elem_size(),
610                    "Mismatched message field type and size");
611           PW_TRY(ReadFixedField(out));
612         }
613         break;
614       }
615       case WireType::kVarint: {
616         // Varint fields call ReadVarintField() for singular case, and either
617         // ReadPackedVarintField() or ReadRepeatedVarintField() for repeated
618         // fields.
619         PW_CHECK(field->elem_size() == sizeof(uint64_t) ||
620                      field->elem_size() == sizeof(uint32_t) ||
621                      field->elem_size() == sizeof(bool),
622                  "Mismatched message field type and size");
623         if (field->is_fixed_size()) {
624           PW_CHECK(field->is_repeated(), "Non-repeated fixed size field");
625           PW_TRY(ReadPackedVarintField(
626               out, field->elem_size(), field->varint_type()));
627         } else if (field->is_repeated()) {
628           // The struct member for this field is a vector of a type
629           // corresponding to the field element size. Cast to the correct
630           // vector type so we're not performing type aliasing (except for
631           // unsigned vs signed which is explicitly allowed).
632           if (field->elem_size() == sizeof(uint64_t)) {
633             auto* vector = reinterpret_cast<pw::Vector<uint64_t>*>(out.data());
634             PW_TRY(ReadRepeatedVarintField(*vector, field->varint_type()));
635           } else if (field->elem_size() == sizeof(uint32_t)) {
636             auto* vector = reinterpret_cast<pw::Vector<uint32_t>*>(out.data());
637             PW_TRY(ReadRepeatedVarintField(*vector, field->varint_type()));
638           } else if (field->elem_size() == sizeof(bool)) {
639             auto* vector = reinterpret_cast<pw::Vector<bool>*>(out.data());
640             PW_TRY(ReadRepeatedVarintField(*vector, field->varint_type()));
641           }
642         } else if (field->is_optional()) {
643           // The struct member for this field is a std::optional of a type
644           // corresponding to the field element size. Cast to the correct
645           // optional type so we're not performing type aliasing (except for
646           // unsigned vs signed which is explicitly allowed), and assign through
647           // a temporary.
648           if (field->elem_size() == sizeof(uint64_t)) {
649             uint64_t value = 0;
650             PW_TRY(ReadVarintField(as_writable_bytes(span(&value, 1)),
651                                    field->varint_type()));
652             auto* optional =
653                 reinterpret_cast<std::optional<uint64_t>*>(out.data());
654             *optional = value;
655           } else if (field->elem_size() == sizeof(uint32_t)) {
656             uint32_t value = 0;
657             PW_TRY(ReadVarintField(as_writable_bytes(span(&value, 1)),
658                                    field->varint_type()));
659             auto* optional =
660                 reinterpret_cast<std::optional<uint32_t>*>(out.data());
661             *optional = value;
662           } else if (field->elem_size() == sizeof(bool)) {
663             bool value = false;
664             PW_TRY(ReadVarintField(as_writable_bytes(span(&value, 1)),
665                                    field->varint_type()));
666             auto* optional = reinterpret_cast<std::optional<bool>*>(out.data());
667             *optional = value;
668           }
669         } else {
670           PW_CHECK(out.size() == field->elem_size(),
671                    "Mismatched message field type and size");
672           PW_TRY(ReadVarintField(out, field->varint_type()));
673         }
674         break;
675       }
676       case WireType::kDelimited: {
677         // Delimited fields are always a singular case because of the inability
678         // to cast to a generic vector with an element of a certain size (we
679         // always need a type).
680         PW_CHECK(!field->is_repeated(),
681                  "Repeated delimited messages always require a callback");
682         if (field->nested_message_fields()) {
683           // Nested Message. Struct member is an embedded struct for the
684           // nested field. Obtain a nested decoder and recursively call Read()
685           // using the fields table pointer from this field.
686           auto nested_decoder = GetNestedDecoder();
687           PW_TRY(nested_decoder.Read(out, *field->nested_message_fields()));
688         } else if (field->is_fixed_size()) {
689           // Fixed-length bytes field. Struct member is a std::array<std::byte>.
690           // Call ReadDelimitedField() to populate it from the stream.
691           PW_CHECK(field->elem_size() == sizeof(std::byte),
692                    "Mismatched message field type and size");
693           PW_TRY(ReadDelimitedField(out));
694         } else {
695           // bytes or string field with a maximum size. The struct member is
696           // pw::Vector<std::byte> for bytes or pw::InlineString<> for string.
697           PW_CHECK(field->elem_size() == sizeof(std::byte),
698                    "Mismatched message field type and size");
699           if (field->is_string()) {
700             PW_TRY(ReadStringOrBytesField<pw::InlineString<>>(out.data()));
701           } else {
702             PW_TRY(ReadStringOrBytesField<pw::Vector<std::byte>>(out.data()));
703           }
704         }
705         break;
706       }
707     }
708   }
709 
710   // Reaching the end of the encoded protobuf is not an error.
711   if (status_ == Status::OutOfRange()) {
712     return OkStatus();
713   }
714 
715   return status_;
716 }
717 
718 }  // namespace pw::protobuf
719