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_memory/internal/sibling_cast.h"
29#include "pw_protobuf/config.h"
30#include "pw_protobuf/internal/codegen.h"
31#include "pw_protobuf/wire_format.h"
32#include "pw_span/span.h"
33#include "pw_status/status.h"
34#include "pw_status/status_with_size.h"
35#include "pw_status/try.h"
36#include "pw_stream/memory_stream.h"
37#include "pw_stream/stream.h"
40namespace pw::protobuf {
56constexpr size_t MaxScratchBufferSize(
size_t max_message_size,
57 size_t max_nested_depth) {
58 return max_message_size + max_nested_depth * config::kMaxVarintSize;
71inline Status WriteVarint(uint64_t value, stream::Writer& writer) {
72 std::array<std::byte, varint::kMaxVarint64SizeBytes> varint_encode_buffer;
73 const size_t varint_size =
75 return writer.Write(span(varint_encode_buffer).first(varint_size));
96inline Status WriteLengthDelimitedKeyAndLengthPrefix(uint32_t field_number,
98 stream::Writer& writer) {
99 PW_TRY(WriteVarint(FieldKey(field_number, WireType::kDelimited), writer));
100 return WriteVarint(payload_size, writer);
126 write_when_empty_(
true),
128 nested_field_number_(0),
129 memory_writer_(scratch_buffer),
163 size_t ConservativeWriteLimit()
const {
164 PW_ASSERT(!nested_encoder_open());
168 enum class EmptyEncoderBehavior { kWriteFieldNumber, kWriteNothing };
179 EmptyEncoderBehavior empty_encoder_behavior =
180 EmptyEncoderBehavior::kWriteFieldNumber) {
181 return GetNestedEncoder(
183 empty_encoder_behavior == EmptyEncoderBehavior::kWriteFieldNumber);
223 template <
typename WriteFunc>
224 Status WriteNestedMessage(uint32_t field_number,
225 WriteFunc write_message,
226 EmptyEncoderBehavior empty_encoder_behavior =
227 EmptyEncoderBehavior::kWriteFieldNumber);
233 PW_ASSERT(!nested_encoder_open());
240 Status WriteUint32(uint32_t field_number, uint32_t value) {
241 return WriteUint64(field_number, value);
248 return WritePackedVarints(
249 field_number, values, internal::VarintType::kNormal);
255 Status WriteRepeatedUint32(uint32_t field_number,
257 return WritePackedVarints(field_number,
258 span(values.data(), values.size()),
259 internal::VarintType::kNormal);
265 Status WriteUint64(uint32_t field_number, uint64_t value) {
266 return WriteVarintField(field_number, value);
273 return WritePackedVarints(
274 field_number, values, internal::VarintType::kNormal);
280 Status WriteRepeatedUint64(uint32_t field_number,
282 return WritePackedVarints(field_number,
283 span(values.data(), values.size()),
284 internal::VarintType::kNormal);
290 Status WriteInt32(uint32_t field_number, int32_t value) {
292 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
299 return WritePackedVarints(
301 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
302 internal::VarintType::kNormal);
308 Status WriteRepeatedInt32(uint32_t field_number,
310 return WritePackedVarints(
312 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
313 internal::VarintType::kNormal);
319 Status WriteInt64(uint32_t field_number, int64_t value) {
321 return WriteUint64(field_number,
static_cast<uint64_t
>(value));
328 return WritePackedVarints(
330 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
331 internal::VarintType::kNormal);
337 Status WriteRepeatedInt64(uint32_t field_number,
339 return WritePackedVarints(
341 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
342 internal::VarintType::kNormal);
348 Status WriteSint32(uint32_t field_number, int32_t value) {
356 return WritePackedVarints(
358 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
359 internal::VarintType::kZigZag);
365 Status WriteRepeatedSint32(uint32_t field_number,
367 return WritePackedVarints(
369 span(
reinterpret_cast<const uint32_t*
>(values.data()), values.size()),
370 internal::VarintType::kZigZag);
376 Status WriteSint64(uint32_t field_number, int64_t value) {
384 return WritePackedVarints(
386 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
387 internal::VarintType::kZigZag);
393 Status WriteRepeatedSint64(uint32_t field_number,
395 return WritePackedVarints(
397 span(
reinterpret_cast<const uint64_t*
>(values.data()), values.size()),
398 internal::VarintType::kZigZag);
404 Status WriteBool(uint32_t field_number,
bool value) {
405 return WriteUint32(field_number,
static_cast<uint32_t
>(value));
412 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
413 "bool must be same size as uint8_t");
414 return WritePackedVarints(
416 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
417 internal::VarintType::kNormal);
423 Status WriteRepeatedBool(uint32_t field_number,
425 static_assert(
sizeof(bool) ==
sizeof(uint8_t),
426 "bool must be same size as uint8_t");
428 return WritePackedVarints(
430 span(
reinterpret_cast<const uint8_t*
>(values.data()), values.size()),
431 internal::VarintType::kNormal);
437 Status WriteFixed32(uint32_t field_number, uint32_t value) {
438 std::array<std::byte,
sizeof(value)> data =
440 return WriteFixed(field_number, data);
446 Status WritePackedFixed32(uint32_t field_number,
448 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint32_t));
454 Status WriteRepeatedFixed32(uint32_t field_number,
456 return WritePackedFixed(field_number,
457 as_bytes(
span(values.data(), values.size())),
464 Status WriteFixed64(uint32_t field_number, uint64_t value) {
465 std::array<std::byte,
sizeof(value)> data =
467 return WriteFixed(field_number, data);
473 Status WritePackedFixed64(uint32_t field_number,
475 return WritePackedFixed(field_number, as_bytes(values),
sizeof(uint64_t));
481 Status WriteRepeatedFixed64(uint32_t field_number,
483 return WritePackedFixed(field_number,
484 as_bytes(
span(values.data(), values.size())),
491 Status WriteSfixed32(uint32_t field_number, int32_t value) {
492 return WriteFixed32(field_number,
static_cast<uint32_t
>(value));
498 Status WritePackedSfixed32(uint32_t field_number,
500 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int32_t));
506 Status WriteRepeatedSfixed32(uint32_t field_number,
508 return WritePackedFixed(field_number,
509 as_bytes(
span(values.data(), values.size())),
516 Status WriteSfixed64(uint32_t field_number, int64_t value) {
517 return WriteFixed64(field_number,
static_cast<uint64_t
>(value));
523 Status WritePackedSfixed64(uint32_t field_number,
525 return WritePackedFixed(field_number, as_bytes(values),
sizeof(int64_t));
531 Status WriteRepeatedSfixed64(uint32_t field_number,
533 return WritePackedFixed(field_number,
534 as_bytes(
span(values.data(), values.size())),
541 Status WriteFloat(uint32_t field_number,
float value) {
542 static_assert(
sizeof(float) ==
sizeof(uint32_t),
543 "Float and uint32_t are not the same size");
544 uint32_t integral_value;
545 std::memcpy(&integral_value, &value,
sizeof(value));
546 std::array<std::byte,
sizeof(value)> data =
548 return WriteFixed(field_number, data);
555 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
float));
561 Status WriteRepeatedFloat(uint32_t field_number,
563 return WritePackedFixed(field_number,
564 as_bytes(
span(values.data(), values.size())),
571 Status WriteDouble(uint32_t field_number,
double value) {
572 static_assert(
sizeof(double) ==
sizeof(uint64_t),
573 "Double and uint64_t are not the same size");
574 uint64_t integral_value;
575 std::memcpy(&integral_value, &value,
sizeof(value));
576 std::array<std::byte,
sizeof(value)> data =
578 return WriteFixed(field_number, data);
585 return WritePackedFixed(field_number, as_bytes(values),
sizeof(
double));
591 Status WriteRepeatedDouble(uint32_t field_number,
593 return WritePackedFixed(field_number,
594 as_bytes(
span(values.data(), values.size())),
604 return WriteLengthDelimitedField(field_number, value);
615 return WriteLengthDelimitedFieldFromCallback(
616 field_number, num_bytes, write_func);
635 Status WriteBytesFromStream(uint32_t field_number,
639 return WriteLengthDelimitedFieldFromStream(
640 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
646 Status WriteString(uint32_t field_number, std::string_view value) {
653 Status WriteString(uint32_t field_number,
const char* value,
size_t len) {
654 return WriteBytes(field_number, as_bytes(span(value, len)));
673 Status WriteStringFromStream(uint32_t field_number,
674 stream::Reader& bytes_reader,
676 ByteSpan stream_pipe_buffer) {
677 return WriteBytesFromStream(
678 field_number, bytes_reader, num_bytes, stream_pipe_buffer);
686 constexpr StreamEncoder(StreamEncoder&& other)
687 : status_(other.status_),
688 write_when_empty_(true),
689 parent_(other.parent_),
690 nested_field_number_(other.nested_field_number_),
691 memory_writer_(std::move(other.memory_writer_)),
692 writer_(&other.writer_ == &other.memory_writer_ ? memory_writer_
694 PW_ASSERT(nested_field_number_ == 0);
697 other.nested_field_number_ = kFirstReservedNumber;
698 other.parent_ =
nullptr;
707 Status Write(span<const std::byte> message,
708 span<const internal::MessageField> table);
713 StreamEncoder GetNestedEncoder(uint32_t field_number,
bool write_when_empty);
716 friend class MemoryEncoder;
718 constexpr StreamEncoder(StreamEncoder& parent,
719 ByteSpan scratch_buffer,
720 bool write_when_empty =
true)
722 write_when_empty_(write_when_empty),
724 nested_field_number_(0),
725 memory_writer_(scratch_buffer),
726 writer_(memory_writer_) {
729 if (&parent !=
this) {
730 status_.
Update(parent.status_);
732 if (scratch_buffer.empty()) {
737 bool nested_encoder_open()
const {
return nested_field_number_ != 0; }
741 void CloseNestedMessage(StreamEncoder& nested);
743 ByteSpan GetNestedScratchBuffer(uint32_t field_number);
746 Status WriteVarintField(uint32_t field_number, uint64_t value);
749 Status WriteLengthDelimitedField(uint32_t field_number, ConstByteSpan data);
751 Status WriteLengthDelimitedFieldFromCallback(
752 uint32_t field_number,
754 const Function<Status(stream::Writer&)>& write_func);
757 Status WriteLengthDelimitedFieldFromStream(uint32_t field_number,
758 stream::Reader& bytes_reader,
760 ByteSpan stream_pipe_buffer);
763 Status WriteFixed(uint32_t field_number, ConstByteSpan data);
768 Status WriteVarint(uint64_t value) {
770 status_.
Update(::pw::protobuf::WriteVarint(value, writer_));
774 Status WriteZigzagVarint(int64_t value) {
779 template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
780 Status WritePackedVarints(uint32_t field_number,
782 internal::VarintType encode_type) {
783 static_assert(std::is_same<T, const uint8_t>::value ||
784 std::is_same<T, const uint32_t>::value ||
785 std::is_same<T, const int32_t>::value ||
786 std::is_same<T, const uint64_t>::value ||
787 std::is_same<T, const int64_t>::value,
788 "Packed varints must be of type bool, uint32_t, int32_t, "
789 "uint64_t, or int64_t");
791 size_t payload_size = 0;
792 for (T val : values) {
793 if (encode_type == internal::VarintType::kZigZag) {
795 static_cast<int64_t
>(
static_cast<std::make_signed_t<T>
>(val));
798 uint64_t integer =
static_cast<uint64_t
>(val);
803 if (!UpdateStatusForWrite(field_number, WireType::kDelimited, payload_size)
808 WriteVarint(FieldKey(field_number, WireType::kDelimited))
810 WriteVarint(payload_size)
812 for (T value : values) {
813 if (encode_type == internal::VarintType::kZigZag) {
814 WriteZigzagVarint(
static_cast<std::make_signed_t<T>
>(value))
828 Status WritePackedFixed(uint32_t field_number,
829 span<const std::byte> values,
832 template <
typename Container>
833 Status WriteStringOrBytes(uint32_t field_number,
834 const std::byte* raw_container) {
835 const auto& container = *
reinterpret_cast<Container*
>(raw_container);
836 if (container.empty()) {
839 return WriteLengthDelimitedField(field_number, as_bytes(span(container)));
842 class AnyMessageWriter;
846 Status DoWriteNestedMessage(uint32_t field_number,
847 AnyMessageWriter
const& write_message,
848 bool write_when_empty);
862 Status UpdateStatusForWrite(uint32_t field_number,
869 void ResetOneOfCallbacks(ConstByteSpan message,
870 span<const internal::MessageField> table);
879 bool write_when_empty_;
885 StreamEncoder* parent_;
889 uint32_t nested_field_number_;
893 stream::MemoryWriter memory_writer_;
896 stream::Writer& writer_;
906 template <
typename WriteFunc>
908 : trampoline_(&Trampoline<WriteFunc>), target_(write_message) {}
911 return trampoline_(target_, encoder);
916 TrampolineSignature* trampoline_;
919 template <
typename WriteFunc>
921 return std::invoke(*
static_cast<WriteFunc*
>(erased_func), encoder);
925template <
typename WriteFunc>
926Status StreamEncoder::WriteNestedMessage(
927 uint32_t field_number,
928 WriteFunc write_message,
929 EmptyEncoderBehavior empty_encoder_behavior) {
930 static_assert(std::is_invocable_r_v<Status, WriteFunc, StreamEncoder&>,
931 "Callable parameter must have signature compatible with "
932 "Status(StreamEncoder&)");
933 return DoWriteNestedMessage(field_number,
935 empty_encoder_behavior ==
936 EmptyEncoderBehavior::kWriteFieldNumber);
973 const std::byte* data()
const {
return memory_writer_.data(); }
974 size_t size()
const {
return memory_writer_.bytes_written(); }
976 const std::byte* begin()
const {
return data(); }
977 const std::byte* end()
const {
return data() + size(); }
1030template <
typename ToStreamEncoder,
typename FromStreamEncoder>
1031inline ToStreamEncoder& StreamEncoderCast(FromStreamEncoder& encoder) {
1032 static_assert(std::is_base_of<StreamEncoder, FromStreamEncoder>::value,
1033 "Provided argument is not a derived class of "
1034 "pw::protobuf::StreamEncoder");
1035 static_assert(std::is_base_of<StreamEncoder, ToStreamEncoder>::value,
1036 "Cannot cast to a type that is not a derived class of "
1037 "pw::protobuf::StreamEncoder");
1038 return pw::internal::SiblingCast<ToStreamEncoder&, StreamEncoder>(encoder);
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:955
Definition: encoder.h:904
Definition: encoder.h:109
Status WriteBytes(uint32_t field_number, size_t num_bytes, const Function< Status(stream::Writer &)> &write_func)
Definition: encoder.h:612
size_t ConservativeWriteLimit() const
Definition: stream.h:229
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: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