diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index de994f458290..e4ec3f106af9 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -48,6 +48,7 @@ #include "absl/container/btree_set.h" #include "absl/strings/ascii.h" +#include "absl/strings/cord.h" #include "absl/strings/escaping.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" @@ -62,6 +63,7 @@ #include "google/protobuf/io/tokenizer.h" #include "google/protobuf/io/zero_copy_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/map_field.h" #include "google/protobuf/message.h" #include "google/protobuf/reflection_mode.h" @@ -1670,8 +1672,8 @@ TextFormat::Parser::~Parser() {} namespace { -bool CheckParseInputSize(absl::string_view input, - io::ErrorCollector* error_collector) { +template +bool CheckParseInputSize(T& input, io::ErrorCollector* error_collector) { if (input.size() > INT_MAX) { error_collector->RecordError( -1, 0, @@ -1709,6 +1711,13 @@ bool TextFormat::Parser::ParseFromString(absl::string_view input, return Parse(&input_stream, output); } +bool TextFormat::Parser::ParseFromCord(const absl::Cord& input, + Message* output) { + DO(CheckParseInputSize(input, error_collector_)); + io::CordInputStream input_stream(&input); + return Parse(&input_stream, output); +} + bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, Message* output) { ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, @@ -1770,6 +1779,11 @@ bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, return Parser().ParseFromString(input, output); } +/* static */ bool TextFormat::ParseFromCord(const absl::Cord& input, + Message* output) { + return Parser().ParseFromCord(input, output); +} + /* static */ bool TextFormat::MergeFromString(absl::string_view input, Message* output) { return Parser().MergeFromString(input, output); diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 74f954b7cb21..6596a2c5fb56 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -45,6 +45,7 @@ #include "google/protobuf/port.h" #include "absl/container/flat_hash_map.h" +#include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" @@ -535,6 +536,8 @@ class PROTOBUF_EXPORT TextFormat { static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. static bool ParseFromString(absl::string_view input, Message* output); + // Like Parse(), but reads directly from a Cord. + static bool ParseFromCord(const absl::Cord& input, Message* output); // Like Parse(), but the data is merged into the given message, as if // using Message::MergeFrom(). @@ -626,6 +629,8 @@ class PROTOBUF_EXPORT TextFormat { bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::ParseFromString(). bool ParseFromString(absl::string_view input, Message* output); + // Like TextFormat::ParseFromCord(). + bool ParseFromCord(const absl::Cord& input, Message* output); // Like TextFormat::Merge(). bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::MergeFromString(). diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 7920accad6bc..1306b71370bc 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -51,6 +51,7 @@ #include "absl/log/absl_check.h" #include "absl/log/die_if_null.h" #include "absl/log/scoped_mock_log.h" +#include "absl/strings/cord.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" @@ -836,6 +837,12 @@ TEST_F(TextFormatTest, ParseBasic) { TestUtil::ExpectAllFieldsSet(proto_); } +TEST_F(TextFormatTest, ParseCordBasic) { + absl::Cord cord(proto_text_format_); + TextFormat::ParseFromCord(cord, &proto_); + TestUtil::ExpectAllFieldsSet(proto_); +} + TEST_F(TextFormatExtensionsTest, ParseExtensions) { io::ArrayInputStream input_stream(proto_text_format_.data(), proto_text_format_.size());