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_protobuf/config.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/try.h"
34#include "pw_stream/memory_stream.h"
35#include "pw_stream/stream.h"
36#include "pw_toolchain/internal/sibling_cast.h"
39namespace pw::protobuf {
55constexpr size_t MaxScratchBufferSize(
size_t max_message_size,
56 size_t max_nested_depth) {
57 return max_message_size + max_nested_depth * config::kMaxVarintSize;
70inline Status WriteVarint(uint64_t value, stream::Writer& writer) {
71 std::array<std::byte, varint::kMaxVarint64SizeBytes> varint_encode_buffer;
72 const size_t varint_size =
74 return writer.Write(span(varint_encode_buffer).first(varint_size));
95inline Status WriteLengthDelimitedKeyAndLengthPrefix(uint32_t field_number,
97 stream::Writer& writer) {
98 PW_TRY(WriteVarint(FieldKey(field_number, WireType::kDelimited), writer));
99 return WriteVarint(payload_size, writer);
125 write_when_empty_(
true),
127 nested_field_number_(0),
128 memory_writer_(scratch_buffer),
162 size_t ConservativeWriteLimit()
const {
163 PW_ASSERT(!nested_encoder_open());
167 enum class EmptyEncoderBehavior { kWriteFieldNumber, kWriteNothing };
178 EmptyEncoderBehavior empty_encoder_behavior =
179 EmptyEncoderBehavior::kWriteFieldNumber) {
180 return GetNestedEncoder(
182 empty_encoder_behavior == EmptyEncoderBehavior::kWriteFieldNumber);
222 template <
typename WriteFunc>
223 Status WriteNestedMessage(uint32_t field_number,
224 WriteFunc write_message,
225 EmptyEncoderBehavior empty_encoder_behavior =
226 EmptyEncoderBehavior::kWriteFieldNumber);
232 PW_ASSERT(!nested_encoder_open());
239 Status WriteUint32(uint32_t field_number, uint32_t value) {
240 return WriteUint64(field_number, value);
247 return WritePackedVarints(
248 field_number, values, internal::VarintType::kNormal);
254 Status WriteRepeatedUint32(uint32_t field_number,
256 return WritePackedVarints(field_number,
257 span(values.data(), values.size()),
258 internal::VarintType::kNormal);
264 Status WriteUint64(uint32_t field_number, uint64_t value) {
265 return WriteVarintField(field_number, value);
272 return WritePackedVarints(
273 field_number, values, internal::VarintType::kNormal);
279 Status WriteRepeatedUint64(uint32_t field_number,
281 return WritePackedVarints(field_number,
282 span(values.data(), values.size()),
283 internal::VarintType::kNormal);
289 Status WriteInt32(uint32_t field_number, int32_t value) {
291 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
298 return WritePackedVarints(
300 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
301 internal::VarintType::kNormal);
307 Status WriteRepeatedInt32(uint32_t field_number,
309 return WritePackedVarints(
311 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
312 internal::VarintType::kNormal);
318 Status WriteInt64(uint32_t field_number, int64_t value) {
320 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
327 return WritePackedVarints(
329 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
330 internal::VarintType::kNormal);
336 Status WriteRepeatedInt64(uint32_t field_number,
338 return WritePackedVarints(
340 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
341 internal::VarintType::kNormal);
347 Status WriteSint32(uint32_t field_number, int32_t value) {
355 return WritePackedVarints(
357 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
358 internal::VarintType::kZigZag);
364 Status WriteRepeatedSint32(uint32_t field_number,
366 return WritePackedVarints(
368 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
369 internal::VarintType::kZigZag);
375 Status WriteSint64(uint32_t field_number, int64_t value) {
383 return WritePackedVarints(
385 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
386 internal::VarintType::kZigZag);
392 Status WriteRepeatedSint64(uint32_t field_number,
394 return WritePackedVarints(
396 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
397 internal::VarintType::kZigZag);
403 Status WriteBool(uint32_t field_number,
bool value) {
404 return WriteUint32(field_number,
static_cast<uint32_t
>(value));
411 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
412 "bool must be same size as uint8_t");
413 return WritePackedVarints(
415 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
416 internal::VarintType::kNormal);
422 Status WriteRepeatedBool(uint32_t field_number,
424 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
425 "bool must be same size as uint8_t");
427 return WritePackedVarints(
429 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
430 internal::VarintType::kNormal);
436 Status WriteFixed32(uint32_t field_number, uint32_t value) {
437 std::array<std::byte,
sizeof(value)> data =
439 return WriteFixed(field_number, data);
445 Status WritePackedFixed32(uint32_t field_number,
447 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint32_t));
453 Status WriteRepeatedFixed32(uint32_t field_number,
455 return WritePackedFixed(field_number,
456 as_bytes(
span(values.data(), values.size())),
463 Status WriteFixed64(uint32_t field_number, uint64_t value) {
464 std::array<std::byte,
sizeof(value)> data =
466 return WriteFixed(field_number, data);
472 Status WritePackedFixed64(uint32_t field_number,
474 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint64_t));
480 Status WriteRepeatedFixed64(uint32_t field_number,
482 return WritePackedFixed(field_number,
483 as_bytes(
span(values.data(), values.size())),
490 Status WriteSfixed32(uint32_t field_number, int32_t value) {
491 return WriteFixed32(field_number,
static_cast<uint32_t
>(value));
497 Status WritePackedSfixed32(uint32_t field_number,
499 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int32_t));
505 Status WriteRepeatedSfixed32(uint32_t field_number,
507 return WritePackedFixed(field_number,
508 as_bytes(
span(values.data(), values.size())),
515 Status WriteSfixed64(uint32_t field_number, int64_t value) {
516 return WriteFixed64(field_number,
static_cast<uint64_t
>(value));
522 Status WritePackedSfixed64(uint32_t field_number,
524 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int64_t));
530 Status WriteRepeatedSfixed64(uint32_t field_number,
532 return WritePackedFixed(field_number,
533 as_bytes(
span(values.data(), values.size())),
540 Status WriteFloat(uint32_t field_number,
float value) {
541 static_assert(
sizeof(float) ==
sizeof(uint32_t),
542 "Float and uint32_t are not the same size");
543 uint32_t integral_value;
544 std::memcpy(&integral_value, &value,
sizeof(value));
545 std::array<std::byte,
sizeof(value)> data =
547 return WriteFixed(field_number, data);
554 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
float));
560 Status WriteRepeatedFloat(uint32_t field_number,
562 return WritePackedFixed(field_number,
563 as_bytes(
span(values.data(), values.size())),
570 Status WriteDouble(uint32_t field_number,
double value) {
571 static_assert(
sizeof(double) ==
sizeof(uint64_t),
572 "Double and uint64_t are not the same size");
573 uint64_t integral_value;
574 std::memcpy(&integral_value, &value,
sizeof(value));
575 std::array<std::byte,
sizeof(value)> data =
577 return WriteFixed(field_number, data);
584 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
double));
590 Status WriteRepeatedDouble(uint32_t field_number,
592 return WritePackedFixed(field_number,
593 as_bytes(
span(values.data(), values.size())),
603 return WriteLengthDelimitedField(field_number, value);
614 return WriteLengthDelimitedFieldFromCallback(
615 field_number, num_bytes, write_func);
634 Status WriteBytesFromStream(uint32_t field_number,
638 return WriteLengthDelimitedFieldFromStream(
639 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
645 Status WriteString(uint32_t field_number, std::string_view value) {
652 Status WriteString(uint32_t field_number,
const char* value,
size_t len) {
653 return WriteBytes(field_number, as_bytes(span(value, len)));
672 Status WriteStringFromStream(uint32_t field_number,
673 stream::Reader& bytes_reader,
675 ByteSpan stream_pipe_buffer) {
676 return WriteBytesFromStream(
677 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
685 constexpr StreamEncoder(StreamEncoder&& other)
686 : status_(other.status_),
687 write_when_empty_(true),
688 parent_(other.parent_),
689 nested_field_number_(other.nested_field_number_),
690 memory_writer_(std::move(other.memory_writer_)),
691 writer_(&other.writer_ == &other.memory_writer_ ? memory_writer_
693 PW_ASSERT(nested_field_number_ == 0);
696 other.nested_field_number_ = kFirstReservedNumber;
697 other.parent_ =
nullptr;
706 Status Write(span<const std::byte> message,
707 span<const internal::MessageField> table);
712 StreamEncoder GetNestedEncoder(uint32_t field_number,
bool write_when_empty);
715 friend class MemoryEncoder;
717 constexpr StreamEncoder(StreamEncoder& parent,
718 ByteSpan scratch_buffer,
719 bool write_when_empty =
true)
721 write_when_empty_(write_when_empty),
723 nested_field_number_(0),
724 memory_writer_(scratch_buffer),
725 writer_(memory_writer_) {
728 if (&parent !=
this) {
729 status_.
Update(parent.status_);
731 if (scratch_buffer.empty()) {
736 bool nested_encoder_open()
const {
return nested_field_number_ != 0; }
740 void CloseNestedMessage(StreamEncoder& nested);
742 ByteSpan GetNestedScratchBuffer(uint32_t field_number);
745 Status WriteVarintField(uint32_t field_number, uint64_t value);
748 Status WriteLengthDelimitedField(uint32_t field_number, ConstByteSpan data);
750 Status WriteLengthDelimitedFieldFromCallback(
751 uint32_t field_number,
753 const Function<Status(stream::Writer&)>& write_func);
756 Status WriteLengthDelimitedFieldFromStream(uint32_t field_number,
757 stream::Reader& bytes_reader,
759 ByteSpan stream_pipe_buffer);
762 Status WriteFixed(uint32_t field_number, ConstByteSpan data);
767 Status WriteVarint(uint64_t value) {
769 status_.
Update(::pw::protobuf::WriteVarint(value, writer_));
773 Status WriteZigzagVarint(int64_t value) {
778 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
779 Status WritePackedVarints(uint32_t field_number,
781 internal::VarintType encode_type) {
782 static_assert(std::is_same<T, const uint8_t>::value ||
783 std::is_same<T, const uint32_t>::value ||
784 std::is_same<T, const int32_t>::value ||
785 std::is_same<T, const uint64_t>::value ||
786 std::is_same<T, const int64_t>::value,
787 "Packed varints must be of type bool, uint32_t, int32_t, "
788 "uint64_t, or int64_t");
790 size_t payload_size = 0;
791 for (T val : values) {
792 if (encode_type == internal::VarintType::kZigZag) {
794 static_cast<int64_t
>(
static_cast<std::make_signed_t<T>
>(val));
797 uint64_t integer =
static_cast<uint64_t
>(val);
802 if (!UpdateStatusForWrite(field_number, WireType::kDelimited, payload_size)
807 WriteVarint(FieldKey(field_number, WireType::kDelimited))
809 WriteVarint(payload_size)
811 for (T value : values) {
812 if (encode_type == internal::VarintType::kZigZag) {
813 WriteZigzagVarint(
static_cast<std::make_signed_t<T>
>(value))
827 Status WritePackedFixed(uint32_t field_number,
828 span<const std::byte> values,
831 template <
typename Container>
832 Status WriteStringOrBytes(uint32_t field_number,
833 const std::byte* raw_container) {
834 const auto& container = *
reinterpret_cast<Container*
>(raw_container);
835 if (container.empty()) {
838 return WriteLengthDelimitedField(field_number, as_bytes(span(container)));
841 class AnyMessageWriter;
845 Status DoWriteNestedMessage(uint32_t field_number,
846 AnyMessageWriter
const& write_message,
847 bool write_when_empty);
861 Status UpdateStatusForWrite(uint32_t field_number,
868 void ResetOneOfCallbacks(ConstByteSpan message,
869 span<const internal::MessageField> table);
878 bool write_when_empty_;
884 StreamEncoder* parent_;
888 uint32_t nested_field_number_;
892 stream::MemoryWriter memory_writer_;
895 stream::Writer& writer_;
905 template <
typename WriteFunc>
907 : trampoline_(&Trampoline<WriteFunc>), target_(write_message) {}
910 return trampoline_(target_, encoder);
915 TrampolineSignature* trampoline_;
918 template <
typename WriteFunc>
920 return std::invoke(*
static_cast<WriteFunc*
>(erased_func), encoder);
924template <
typename WriteFunc>
925Status StreamEncoder::WriteNestedMessage(
926 uint32_t field_number,
927 WriteFunc write_message,
928 EmptyEncoderBehavior empty_encoder_behavior) {
929 static_assert(std::is_invocable_r_v<Status, WriteFunc, StreamEncoder&>,
930 "Callable parameter must have signature compatible with "
931 "Status(StreamEncoder&)");
932 return DoWriteNestedMessage(field_number,
934 empty_encoder_behavior ==
935 EmptyEncoderBehavior::kWriteFieldNumber);
972 const std::byte* data()
const {
return memory_writer_.data(); }
973 size_t size()
const {
return memory_writer_.bytes_written(); }
975 const std::byte* begin()
const {
return data(); }
976 const std::byte* end()
const {
return data() + size(); }
1025template <
typename ToStreamEncoder,
typename FromStreamEncoder>
1026inline ToStreamEncoder& StreamEncoderCast(FromStreamEncoder& encoder) {
1027 static_assert(std::is_base_of<StreamEncoder, FromStreamEncoder>::value,
1028 "Provided argument is not a derived class of "
1029 "pw::protobuf::StreamEncoder");
1030 static_assert(std::is_base_of<StreamEncoder, ToStreamEncoder>::value,
1031 "Cannot cast to a type that is not a derived class of "
1032 "pw::protobuf::StreamEncoder");
1033 return pw::internal::SiblingCast<ToStreamEncoder&, StreamEncoder>(encoder);
constexpr void Update(Status other)
Definition: status.h:272
constexpr void IgnoreError() const
Definition: status.h:283
static constexpr Status ResourceExhausted()
Definition: status.h:157
Definition: encoder.h:954
Definition: encoder.h:903
Definition: encoder.h:108
Status WriteBytes(uint32_t field_number, size_t num_bytes, const Function< Status(stream::Writer &)> &write_func)
Definition: encoder.h:611
size_t ConservativeWriteLimit() const
Definition: stream.h:254
constexpr void CopyInOrder(endian order, T value, U *dest)
Definition: endian.h:145
fit::function_impl< function_internal::config::kInlineCallableSize, !function_internal::config::kEnableDynamicAllocation, FunctionType, PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE > Function
Definition: function.h:73
#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:297
constexpr std::make_unsigned_t< T > ZigZagEncode(T n)
Definition: varint.h:204
constexpr size_t EncodedSize(T integer)
Computes the size of an integer when encoded as a varint.
Definition: varint.h:232
size_t EncodeLittleEndianBase128(uint64_t integer, const span< std::byte > &output)
Definition: varint.h:242