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