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