Coverage Report

Created: 2026-02-14 07:14

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