In `SerializedMessage{,Backward}Writer`, rename `CopyString()` to
`WriteString()`, merging it with other overloads.
Add direct support for `CordIteratorSpan` in `WriteString()`. It is convertible
to `absl::Cord`, but the stringification mechanism does not find that.
Rationale: it is not that important to explicitly indicate whether reading is
destructive or not, especially since `ReaderSpan` is move-only. It is more
important to be able to treat `ReaderSpan`, `CordIteratorSpan`, and
`absl::string_view` uniformly.
PiperOrigin-RevId: 847835642
diff --git a/riegeli/messages/BUILD b/riegeli/messages/BUILD
index c9b167f..4d1852a 100644
--- a/riegeli/messages/BUILD
+++ b/riegeli/messages/BUILD
@@ -199,6 +199,7 @@
"//riegeli/base:any",
"//riegeli/base:arithmetic",
"//riegeli/base:assert",
+ "//riegeli/base:buffering",
"//riegeli/base:constexpr",
"//riegeli/base:cord_iterator_span",
"//riegeli/base:types",
@@ -234,6 +235,8 @@
"//riegeli/base:any",
"//riegeli/base:arithmetic",
"//riegeli/base:assert",
+ "//riegeli/base:buffering",
+ "//riegeli/base:cord_iterator_span",
"//riegeli/base:types",
"//riegeli/bytes:backward_writer",
"//riegeli/bytes:copy_all",
diff --git a/riegeli/messages/field_handlers.h b/riegeli/messages/field_handlers.h
index 2a15b45..d7afde0 100644
--- a/riegeli/messages/field_handlers.h
+++ b/riegeli/messages/field_handlers.h
@@ -408,7 +408,8 @@
// `ReaderSpan<>`, `CordIteratorSpan`, and `absl::string_view`, then the action
// parameter can be declared as `auto`. This is convenient if the implementation
// can treat these types uniformly, e.g. when the value is passed to
-// `riegeli::ParseMessage()` or `SerializedMessageReader2::ReadMessage()`.
+// `riegeli::ParseMessage()`, `SerializedMessageReader2::ReadMessage()`, or
+// `SerializedMessageWriter::WriteString()`.
//
// Alternatively, the action can use `absl::Overload{}` to provide variants with
// separate implementations for these parameter types.
diff --git a/riegeli/messages/serialized_message_backward_writer.cc b/riegeli/messages/serialized_message_backward_writer.cc
index a2152bf..2bc2bd9 100644
--- a/riegeli/messages/serialized_message_backward_writer.cc
+++ b/riegeli/messages/serialized_message_backward_writer.cc
@@ -25,6 +25,8 @@
#include "absl/strings/str_cat.h"
#include "riegeli/base/any.h"
#include "riegeli/base/assert.h"
+#include "riegeli/base/buffering.h"
+#include "riegeli/base/cord_iterator_span.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/backward_writer.h"
#include "riegeli/bytes/copy_all.h"
@@ -42,15 +44,16 @@
length));
}
-absl::Status SerializedMessageBackwardWriter::CopyStringFailed(
+absl::Status SerializedMessageBackwardWriter::WriteStringFailed(
Reader& src, BackwardWriter& dest) {
- return !dest.ok() ? dest.status()
- : src.StatusOrAnnotate(absl::InvalidArgumentError(
- "Could not read a length-delimited field"));
+ return !dest.ok()
+ ? dest.status()
+ : src.StatusOrAnnotate(absl::InvalidArgumentError(
+ "Could not read contents for a length-delimited field"));
}
-absl::Status SerializedMessageBackwardWriter::CopyString(int field_number,
- AnyRef<Reader*> src) {
+absl::Status SerializedMessageBackwardWriter::WriteString(int field_number,
+ AnyRef<Reader*> src) {
if (src.IsOwning()) src->SetReadAllHint(true);
const Position pos_after = writer().pos();
if (absl::Status status = CopyAll(std::move(src), writer());
@@ -62,6 +65,19 @@
return WriteLengthUnchecked(field_number, writer().pos() - pos_after);
}
+absl::Status SerializedMessageBackwardWriter::WriteString(
+ int field_number, CordIteratorSpan src) {
+ if (src.length() <= kMaxBytesToCopy) {
+ if (ABSL_PREDICT_FALSE(!writer().Push(src.length()))) {
+ return writer().status();
+ }
+ writer().move_cursor(src.length());
+ CordIteratorSpan::Read(src.iterator(), src.length(), writer().cursor());
+ return WriteLengthUnchecked(field_number, src.length());
+ }
+ return WriteString(field_number, std::move(src).ToCord());
+}
+
void SerializedMessageBackwardWriter::OpenLengthDelimited() {
submessages_.push_back(writer().pos());
}
diff --git a/riegeli/messages/serialized_message_backward_writer.h b/riegeli/messages/serialized_message_backward_writer.h
index 88cb8b3..8699555 100644
--- a/riegeli/messages/serialized_message_backward_writer.h
+++ b/riegeli/messages/serialized_message_backward_writer.h
@@ -28,11 +28,11 @@
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/status/status.h"
-#include "absl/strings/string_view.h"
#include "google/protobuf/message_lite.h"
#include "riegeli/base/any.h"
#include "riegeli/base/arithmetic.h"
#include "riegeli/base/assert.h"
+#include "riegeli/base/cord_iterator_span.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/backward_writer.h"
#include "riegeli/bytes/limiting_reader.h"
@@ -158,19 +158,10 @@
requires(IsStringifiable<Values>::value && ...)
#endif
absl::Status WriteString(int field_number, Values&&... values);
-
- // Writes the field tag of a length-delimited field and copies the field value
- // from a `Reader`.
- //
- // For `absl::string_view`, this is equivalent to `WriteString()`.
- // This is useful for generic handlers of length-delimited fields for
- // `SerializedMessageReader2`.
- absl::Status CopyString(int field_number, AnyRef<Reader*> src);
+ absl::Status WriteString(int field_number, AnyRef<Reader*> src);
template <typename ReaderType>
- absl::Status CopyString(int field_number, ReaderSpan<ReaderType> src);
- absl::Status CopyString(int field_number, absl::string_view src) {
- return WriteString(field_number, src);
- }
+ absl::Status WriteString(int field_number, ReaderSpan<ReaderType> src);
+ absl::Status WriteString(int field_number, CordIteratorSpan src);
// Writes the field tag of a length-delimited field and serializes a message
// as the field value.
@@ -245,7 +236,7 @@
private:
ABSL_ATTRIBUTE_COLD static absl::Status LengthOverflowError(Position length);
- ABSL_ATTRIBUTE_COLD static absl::Status CopyStringFailed(
+ ABSL_ATTRIBUTE_COLD static absl::Status WriteStringFailed(
Reader& src, BackwardWriter& dest);
BackwardWriter* absl_nullable dest_ = nullptr;
@@ -503,7 +494,7 @@
}
template <typename ReaderType>
-absl::Status SerializedMessageBackwardWriter::CopyString(
+absl::Status SerializedMessageBackwardWriter::WriteString(
int field_number, ReaderSpan<ReaderType> src) {
if (ABSL_PREDICT_FALSE(src.length() >
uint32_t{std::numeric_limits<int32_t>::max()})) {
@@ -511,7 +502,7 @@
}
if (ABSL_PREDICT_FALSE(
!src.reader().Copy(IntCast<size_t>(src.length()), writer()))) {
- return CopyStringFailed(src.reader(), writer());
+ return WriteStringFailed(src.reader(), writer());
}
return WriteLengthUnchecked(field_number, src.length());
}
diff --git a/riegeli/messages/serialized_message_writer.cc b/riegeli/messages/serialized_message_writer.cc
index 8bbf2d7..2b3999f 100644
--- a/riegeli/messages/serialized_message_writer.cc
+++ b/riegeli/messages/serialized_message_writer.cc
@@ -29,6 +29,8 @@
#include "riegeli/base/any.h"
#include "riegeli/base/arithmetic.h"
#include "riegeli/base/assert.h"
+#include "riegeli/base/buffering.h"
+#include "riegeli/base/cord_iterator_span.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/cord_writer.h"
#include "riegeli/bytes/limiting_reader.h"
@@ -46,22 +48,23 @@
length));
}
-absl::Status SerializedMessageWriter::CopyStringFailed(Reader& src,
- Writer& dest) {
- return !dest.ok() ? dest.status()
- : src.StatusOrAnnotate(absl::InvalidArgumentError(
- "Could not read a length-delimited field"));
+absl::Status SerializedMessageWriter::WriteStringFailed(Reader& src,
+ Writer& dest) {
+ return !dest.ok()
+ ? dest.status()
+ : src.StatusOrAnnotate(absl::InvalidArgumentError(
+ "Could not read contents for a length-delimited field"));
}
-absl::Status SerializedMessageWriter::CopyString(int field_number,
- AnyRef<Reader*> src) {
+absl::Status SerializedMessageWriter::WriteString(int field_number,
+ AnyRef<Reader*> src) {
if (src.IsOwning()) src->SetReadAllHint(true);
if (src->SupportsSize()) {
const std::optional<Position> size = src->Size();
if (ABSL_PREDICT_FALSE(size == std::nullopt)) return src->status();
- if (absl::Status status =
- CopyString(field_number,
- ReaderSpan(src.get(), SaturatingSub(*size, src->pos())));
+ if (absl::Status status = WriteString(
+ field_number,
+ ReaderSpan(src.get(), SaturatingSub(*size, src->pos())));
ABSL_PREDICT_FALSE(!status.ok())) {
return status;
}
@@ -79,6 +82,23 @@
}
}
+absl::Status SerializedMessageWriter::WriteString(int field_number,
+ CordIteratorSpan src) {
+ if (src.length() <= kMaxBytesToCopy) {
+ if (absl::Status status = WriteLengthUnchecked(field_number, src.length());
+ ABSL_PREDICT_FALSE(!status.ok())) {
+ return status;
+ }
+ if (ABSL_PREDICT_FALSE(!writer().Push(src.length()))) {
+ return writer().status();
+ }
+ CordIteratorSpan::Read(src.iterator(), src.length(), writer().cursor());
+ writer().move_cursor(src.length());
+ return absl::OkStatus();
+ }
+ return WriteString(field_number, std::move(src).ToCord());
+}
+
void SerializedMessageWriter::OpenLengthDelimited() {
writer_ = &submessages_.emplace_back();
}
diff --git a/riegeli/messages/serialized_message_writer.h b/riegeli/messages/serialized_message_writer.h
index 7f6dbbb..368bfda 100644
--- a/riegeli/messages/serialized_message_writer.h
+++ b/riegeli/messages/serialized_message_writer.h
@@ -154,19 +154,10 @@
requires(IsStringifiable<Values>::value && ...)
#endif
absl::Status WriteString(int field_number, Values&&... values);
-
- // Writes the field tag of a length-delimited field and copies the field value
- // from a `Reader`.
- //
- // For `absl::string_view`, this is equivalent to `WriteString()`.
- // This is useful for generic handlers of length-delimited fields for
- // `SerializedMessageReader2`.
- absl::Status CopyString(int field_number, AnyRef<Reader*> src);
+ absl::Status WriteString(int field_number, AnyRef<Reader*> src);
template <typename ReaderType>
- absl::Status CopyString(int field_number, ReaderSpan<ReaderType> src);
- absl::Status CopyString(int field_number, absl::string_view src) {
- return WriteString(field_number, src);
- }
+ absl::Status WriteString(int field_number, ReaderSpan<ReaderType> src);
+ absl::Status WriteString(int field_number, CordIteratorSpan src);
// Writes the field tag of a length-delimited field and serializes a message
// as the field value.
@@ -329,8 +320,8 @@
private:
ABSL_ATTRIBUTE_COLD static absl::Status LengthOverflowError(Position length);
- ABSL_ATTRIBUTE_COLD static absl::Status CopyStringFailed(Reader& src,
- Writer& dest);
+ ABSL_ATTRIBUTE_COLD static absl::Status WriteStringFailed(Reader& src,
+ Writer& dest);
Writer* absl_nullable dest_ = nullptr;
std::vector<CordWriter<absl::Cord>> submessages_;
@@ -393,7 +384,8 @@
absl::Status DynamicHandleLengthDelimitedFromReader(
int field_number, ReaderSpan<> repr, Context&... context) const {
- return message_writer(context...).CopyString(field_number, std::move(repr));
+ return message_writer(context...)
+ .WriteString(field_number, std::move(repr));
}
absl::Status DynamicHandleLengthDelimitedFromCord(
@@ -702,14 +694,14 @@
}
template <typename ReaderType>
-absl::Status SerializedMessageWriter::CopyString(int field_number,
- ReaderSpan<ReaderType> src) {
+absl::Status SerializedMessageWriter::WriteString(int field_number,
+ ReaderSpan<ReaderType> src) {
if (absl::Status status = WriteLengthUnchecked(field_number, src.length());
ABSL_PREDICT_FALSE(!status.ok())) {
return status;
}
if (ABSL_PREDICT_FALSE(!src.reader().Copy(src.length(), writer()))) {
- return CopyStringFailed(src.reader(), writer());
+ return WriteStringFailed(src.reader(), writer());
}
return absl::OkStatus();
}