23#include "pw_assert/assert.h"
24#include "pw_bytes/bit.h"
25#include "pw_bytes/endian.h"
26#include "pw_bytes/span.h"
27#include "pw_containers/vector.h"
28#include "pw_function/function_ref.h"
29#include "pw_memory/internal/sibling_cast.h"
30#include "pw_protobuf/config.h"
31#include "pw_protobuf/internal/codegen.h"
32#include "pw_protobuf/wire_format.h"
33#include "pw_span/span.h"
34#include "pw_status/status.h"
35#include "pw_status/status_with_size.h"
36#include "pw_status/try.h"
37#include "pw_stream/memory_stream.h"
38#include "pw_stream/stream.h"
41namespace pw::protobuf {
57constexpr size_t MaxScratchBufferSize(
size_t max_message_size,
58 size_t max_nested_depth) {
59 return max_message_size + max_nested_depth * config::kMaxVarintSize;
72inline Status WriteVarint(uint64_t value, stream::Writer& writer) {
73 std::array<std::byte, varint::kMaxVarint64SizeBytes> varint_encode_buffer;
74 const size_t varint_size =
76 return writer.Write(span(varint_encode_buffer).first(varint_size));
97inline Status WriteLengthDelimitedKeyAndLengthPrefix(uint32_t field_number,
99 stream::Writer& writer) {
100 PW_TRY(WriteVarint(FieldKey(field_number, WireType::kDelimited), writer));
101 return WriteVarint(payload_size, writer);
127 write_when_empty_(
true),
129 nested_field_number_(0),
130 memory_writer_(scratch_buffer),
164 size_t ConservativeWriteLimit()
const {
165 PW_ASSERT(!nested_encoder_open());
169 enum class EmptyEncoderBehavior { kWriteFieldNumber, kWriteNothing };
180 EmptyEncoderBehavior empty_encoder_behavior =
181 EmptyEncoderBehavior::kWriteFieldNumber) {
182 return GetNestedEncoder(
184 empty_encoder_behavior == EmptyEncoderBehavior::kWriteFieldNumber);
216 Status WriteNestedMessage(uint32_t field_number,
218 EmptyEncoderBehavior empty_encoder_behavior =
219 EmptyEncoderBehavior::kWriteFieldNumber);
225 PW_ASSERT(!nested_encoder_open());
232 Status WriteUint32(uint32_t field_number, uint32_t value) {
233 return WriteUint64(field_number, value);
240 return WritePackedVarints(
241 field_number, values, internal::VarintType::kNormal);
247 template <
typename T,
typename = std::enable_if_t<std::is_enum_v<T>>>
249 static_assert(
sizeof(T) ==
sizeof(int32_t),
250 "Protobuf enums are always 4-byte integers");
251 return WriteGenericPackedVarints<
252 std::remove_cv_t<std::underlying_type_t<T>>>(
254 reinterpret_cast<const std::byte*
>(values.data()),
256 internal::VarintType::kNormal);
262 Status WriteRepeatedUint32(uint32_t field_number,
264 return WritePackedVarints(
265 field_number, values, internal::VarintType::kNormal);
271 Status WriteUint64(uint32_t field_number, uint64_t value) {
272 return WriteVarintField(field_number, value);
279 return WritePackedVarints(
280 field_number, values, internal::VarintType::kNormal);
286 Status WriteRepeatedUint64(uint32_t field_number,
288 return WritePackedVarints(
289 field_number, values, internal::VarintType::kNormal);
295 Status WriteInt32(uint32_t field_number, int32_t value) {
297 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
304 return WritePackedVarints(
305 field_number, values, internal::VarintType::kNormal);
311 Status WriteRepeatedInt32(uint32_t field_number,
313 return WritePackedVarints(
314 field_number, values, internal::VarintType::kNormal);
320 Status WriteInt64(uint32_t field_number, int64_t value) {
322 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
329 return WritePackedVarints(
330 field_number, values, internal::VarintType::kNormal);
336 Status WriteRepeatedInt64(uint32_t field_number,
338 return WritePackedVarints(
339 field_number, values, internal::VarintType::kNormal);
345 Status WriteSint32(uint32_t field_number, int32_t value) {
353 return WritePackedVarints(
354 field_number, values, internal::VarintType::kZigZag);
360 Status WriteRepeatedSint32(uint32_t field_number,
362 return WritePackedVarints(
363 field_number, values, internal::VarintType::kZigZag);
369 Status WriteSint64(uint32_t field_number, int64_t value) {
377 return WritePackedVarints(
378 field_number, values, internal::VarintType::kZigZag);
384 Status WriteRepeatedSint64(uint32_t field_number,
386 return WritePackedVarints(
387 field_number, values, internal::VarintType::kZigZag);
393 Status WriteBool(uint32_t field_number,
bool value) {
394 return WriteUint32(field_number,
static_cast<uint32_t
>(value));
401 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
402 "bool must be same size as uint8_t");
403 return WritePackedVarints(
405 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
406 internal::VarintType::kNormal);
412 Status WriteRepeatedBool(uint32_t field_number,
414 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
415 "bool must be same size as uint8_t");
417 return WritePackedVarints(
419 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
420 internal::VarintType::kNormal);
426 Status WriteFixed32(uint32_t field_number, uint32_t value) {
427 std::array<std::byte,
sizeof(value)> data =
429 return WriteFixed(field_number, data);
435 Status WritePackedFixed32(uint32_t field_number,
437 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint32_t));
443 Status WriteRepeatedFixed32(uint32_t field_number,
445 return WritePackedFixed(field_number,
446 as_bytes(
span(values.data(), values.size())),
453 Status WriteFixed64(uint32_t field_number, uint64_t value) {
454 std::array<std::byte,
sizeof(value)> data =
456 return WriteFixed(field_number, data);
462 Status WritePackedFixed64(uint32_t field_number,
464 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint64_t));
470 Status WriteRepeatedFixed64(uint32_t field_number,
472 return WritePackedFixed(field_number,
473 as_bytes(
span(values.data(), values.size())),
480 Status WriteSfixed32(uint32_t field_number, int32_t value) {
481 return WriteFixed32(field_number,
static_cast<uint32_t
>(value));
487 Status WritePackedSfixed32(uint32_t field_number,
489 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int32_t));
495 Status WriteRepeatedSfixed32(uint32_t field_number,
497 return WritePackedFixed(field_number,
498 as_bytes(
span(values.data(), values.size())),
505 Status WriteSfixed64(uint32_t field_number, int64_t value) {
506 return WriteFixed64(field_number,
static_cast<uint64_t
>(value));
512 Status WritePackedSfixed64(uint32_t field_number,
514 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int64_t));
520 Status WriteRepeatedSfixed64(uint32_t field_number,
522 return WritePackedFixed(field_number,
523 as_bytes(
span(values.data(), values.size())),
530 Status WriteFloat(uint32_t field_number,
float value) {
531 static_assert(
sizeof(float) ==
sizeof(uint32_t),
532 "Float and uint32_t are not the same size");
533 uint32_t integral_value;
534 std::memcpy(&integral_value, &value,
sizeof(value));
535 std::array<std::byte,
sizeof(value)> data =
537 return WriteFixed(field_number, data);
544 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
float));
550 Status WriteRepeatedFloat(uint32_t field_number,
552 return WritePackedFixed(field_number,
553 as_bytes(
span(values.data(), values.size())),
560 Status WriteDouble(uint32_t field_number,
double value) {
561 static_assert(
sizeof(double) ==
sizeof(uint64_t),
562 "Double and uint64_t are not the same size");
563 uint64_t integral_value;
564 std::memcpy(&integral_value, &value,
sizeof(value));
565 std::array<std::byte,
sizeof(value)> data =
567 return WriteFixed(field_number, data);
574 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
double));
580 Status WriteRepeatedDouble(uint32_t field_number,
582 return WritePackedFixed(field_number,
583 as_bytes(
span(values.data(), values.size())),
593 return WriteLengthDelimitedField(field_number, value);
604 return WriteLengthDelimitedFieldFromCallback(
605 field_number, num_bytes, write_func);
624 Status WriteBytesFromStream(uint32_t field_number,
628 return WriteLengthDelimitedFieldFromStream(
629 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
635 Status WriteString(uint32_t field_number, std::string_view value) {
642 Status WriteString(uint32_t field_number,
const char* value,
size_t len) {
643 return WriteBytes(field_number, as_bytes(span(value, len)));
662 Status WriteStringFromStream(uint32_t field_number,
663 stream::Reader& bytes_reader,
665 ByteSpan stream_pipe_buffer) {
666 return WriteBytesFromStream(
667 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
675 constexpr StreamEncoder(StreamEncoder&& other)
676 : status_(other.status_),
677 write_when_empty_(true),
678 parent_(other.parent_),
679 nested_field_number_(other.nested_field_number_),
680 memory_writer_(std::move(other.memory_writer_)),
681 writer_(&other.writer_ == &other.memory_writer_ ? memory_writer_
683 PW_ASSERT(nested_field_number_ == 0);
686 other.nested_field_number_ = kFirstReservedNumber;
687 other.parent_ =
nullptr;
696 Status Write(span<const std::byte> message,
697 span<const internal::MessageField> table);
702 StreamEncoder GetNestedEncoder(uint32_t field_number,
bool write_when_empty);
705 friend class MemoryEncoder;
707 constexpr StreamEncoder(StreamEncoder& parent,
708 ByteSpan scratch_buffer,
709 bool write_when_empty =
true)
711 write_when_empty_(write_when_empty),
713 nested_field_number_(0),
714 memory_writer_(scratch_buffer),
715 writer_(memory_writer_) {
718 if (&parent !=
this) {
719 status_.
Update(parent.status_);
721 if (scratch_buffer.empty()) {
726 bool nested_encoder_open()
const {
return nested_field_number_ != 0; }
730 void CloseNestedMessage(StreamEncoder& nested);
732 ByteSpan GetNestedScratchBuffer(uint32_t field_number);
735 Status WriteVarintField(uint32_t field_number, uint64_t value);
738 Status WriteLengthDelimitedField(uint32_t field_number, ConstByteSpan data);
740 Status WriteLengthDelimitedFieldFromCallback(
741 uint32_t field_number,
743 FunctionRef<Status(stream::Writer&)> write_func);
746 Status WriteLengthDelimitedFieldFromStream(uint32_t field_number,
747 stream::Reader& bytes_reader,
749 ByteSpan stream_pipe_buffer);
752 Status WriteFixed(uint32_t field_number, ConstByteSpan data);
757 Status WriteVarint(uint64_t value) {
759 status_.
Update(::pw::protobuf::WriteVarint(value, writer_));
763 Status WriteZigzagVarint(int64_t value) {
767 template <
typename U,
bool IsEnum = std::is_enum_v<U>>
768 struct UnderlyingType {
769 using type = std::underlying_type_t<U>;
772 template <
typename U>
773 struct UnderlyingType<U, false> {
778 template <
typename Span>
779 Status WritePackedVarints(uint32_t field_number,
781 internal::VarintType encode_type) {
782 using T = std::remove_cv_t<
783 typename UnderlyingType<typename Span::value_type>::type>;
784 static_assert(std::is_same_v<T, uint8_t> || std::is_same_v<T, uint32_t> ||
785 std::is_same_v<T, int32_t> ||
786 std::is_same_v<T, uint64_t> || std::is_same_v<T, int64_t>,
787 "Packed varints must be of type bool, uint32_t, int32_t, "
788 "uint64_t, int64_t, or an enum");
789 return WriteGenericPackedVarints<T>(
791 reinterpret_cast<const std::byte*
>(values.data()),
798 template <
typename T>
799 Status WriteGenericPackedVarints(uint32_t field_number,
800 const std::byte* data,
802 internal::VarintType encode_type) {
803 static_assert(std::is_integral_v<T>,
"T must be an integral type");
808 auto get_value = [encode_type](T v) -> uint64_t {
809 if (encode_type == internal::VarintType::kZigZag) {
810 if constexpr (std::is_signed_v<T>) {
814 return static_cast<uint64_t
>(v);
818 size_t payload_size = 0;
819 for (
size_t i = 0; i < count; ++i) {
821 std::memcpy(&raw_value, data + i *
sizeof(T),
sizeof(T));
826 UpdateStatusForWrite(field_number, WireType::kDelimited, payload_size));
828 WriteVarint(FieldKey(field_number, WireType::kDelimited)).
IgnoreError();
832 for (
size_t i = 0; i < count; ++i) {
834 std::memcpy(&raw_value, data + i *
sizeof(T),
sizeof(T));
844 Status WritePackedFixed(uint32_t field_number,
845 span<const std::byte> values,
848 template <
typename Container>
849 Status WriteStringOrBytes(uint32_t field_number,
850 const std::byte* raw_container) {
851 const auto& container = *
reinterpret_cast<Container*
>(raw_container);
852 if (container.empty()) {
855 return WriteLengthDelimitedField(field_number, as_bytes(span(container)));
870 Status UpdateStatusForWrite(uint32_t field_number,
877 void ResetOneOfCallbacks(ConstByteSpan message,
878 span<const internal::MessageField> table);
887 bool write_when_empty_;
893 StreamEncoder* parent_;
897 uint32_t nested_field_number_;
901 stream::MemoryWriter memory_writer_;
904 stream::Writer& writer_;
941 const std::byte* data()
const {
return memory_writer_.data(); }
942 size_t size()
const {
return memory_writer_.bytes_written(); }
944 const std::byte* begin()
const {
return data(); }
945 const std::byte* end()
const {
return data() + size(); }
998template <
typename ToStreamEncoder,
typename FromStreamEncoder>
999inline ToStreamEncoder& StreamEncoderCast(FromStreamEncoder& encoder) {
1000 static_assert(std::is_base_of<StreamEncoder, FromStreamEncoder>::value,
1001 "Provided argument is not a derived class of "
1002 "pw::protobuf::StreamEncoder");
1003 static_assert(std::is_base_of<StreamEncoder, ToStreamEncoder>::value,
1004 "Cannot cast to a type that is not a derived class of "
1005 "pw::protobuf::StreamEncoder");
1006 return pw::internal::SiblingCast<ToStreamEncoder&, StreamEncoder>(encoder);
Definition: function_ref.h:43
constexpr void Update(Status other)
Definition: status.h:419
constexpr void IgnoreError() const
Definition: status.h:430
static constexpr Status ResourceExhausted()
Definition: status.h:230
Definition: status_with_size.h:51
Definition: encoder.h:923
Definition: encoder.h:110
Status WriteBytes(uint32_t field_number, size_t num_bytes, FunctionRef< Status(stream::Writer &)> write_func)
Definition: encoder.h:601
size_t ConservativeWriteLimit() const
Definition: stream.h:229
constexpr void CopyInOrder(endian order, T value, U *dest)
Definition: endian.h:145
#define PW_TRY(expr)
Returns early if expr is a non-OK Status or Result.
Definition: try.h:27
constexpr Status OkStatus()
Definition: status.h:450
constexpr std::make_unsigned_t< T > ZigZagEncode(T value)
Definition: varint.h:365
constexpr size_t EncodeLittleEndianBase128(uint64_t value, ByteSpan out_encoded)
Definition: varint.h:372
constexpr size_t EncodedSize(T value)
Computes the size of an integer when encoded as a varint.
Definition: varint.h:123