Add Cord based Parse and Serialize logic to MessageLite

PiperOrigin-RevId: 494887062
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 75f5446..c4a1f15 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -32,6 +32,7 @@
 
 #include <climits>
 #include <iostream>
+#include <limits>
 #include <string>
 #include <utility>
 
@@ -56,6 +57,7 @@
 
 namespace google {
 namespace protobuf {
+namespace {
 
 // Helper methods to test parsing merge behavior.
 void ExpectMessageMerged(const unittest::TestAllTypesLite& message) {
@@ -73,13 +75,39 @@
   msg3->set_optional_string("hello");
 }
 
+// Declare and define the template `T SerializeAs()` function which we
+// specialize for the typed tests serializing to a string or Cord.
+template <typename T>
+T SerializeAs(const MessageLite& msg);
+
+template <>
+std::string SerializeAs<std::string>(const MessageLite& msg) {
+  return msg.SerializeAsString();
+}
+
+template <>
+absl::Cord SerializeAs<absl::Cord>(const MessageLite& msg) {
+  return msg.SerializeAsCord();
+}
+
+// `ParseFrom()` is overloaded for string and Cord and used in the
+// typed tests parsing from string and Cord values.
+bool ParseFrom(const std::string& data, MessageLite& msg) {
+  return msg.ParseFromString(data);
+}
+
+bool ParseFrom(const absl::Cord& data, MessageLite& msg) {
+  return msg.ParseFromCord(data);
+}
+
+template <typename T>
 void SetAllTypesInEmptyMessageUnknownFields(
     unittest::TestEmptyMessageLite* empty_message) {
   protobuf_unittest::TestAllTypesLite message;
   TestUtilLite::ExpectClear(message);
   TestUtilLite::SetAllFields(&message);
-  std::string data = message.SerializeAsString();
-  empty_message->ParseFromString(data);
+  T data = SerializeAs<T>(message);
+  ParseFrom(data, *empty_message);
 }
 
 void SetSomeTypesInEmptyMessageUnknownFields(
@@ -149,16 +177,27 @@
   test_value(std::numeric_limits<uint64_t>::max(), 10);
 }
 
-TEST(Lite, AllLite1) {
-  std::string data;
+template <typename T>
+class LiteTest : public ::testing::Test {};
 
+struct TypedTestName {
+  template <typename T>
+  static std::string GetName(int /*i*/) {
+    return std::is_same<T, absl::Cord>::value ? "Cord" : "String";
+  }
+};
+
+using SerializedDataTypes = ::testing::Types<std::string, absl::Cord>;
+TYPED_TEST_SUITE(LiteTest, SerializedDataTypes, TypedTestName);
+
+TYPED_TEST(LiteTest, AllLite1) {
   {
     protobuf_unittest::TestAllTypesLite message, message2, message3;
     TestUtilLite::ExpectClear(message);
     TestUtilLite::SetAllFields(&message);
-    message2.CopyFrom(message);
-    data = message.SerializeAsString();
-    message3.ParseFromString(data);
+    message2 = message;
+    TypeParam data = SerializeAs<TypeParam>(message2);
+    ParseFrom(data, message3);
     TestUtilLite::ExpectAllFieldsSet(message);
     TestUtilLite::ExpectAllFieldsSet(message2);
     TestUtilLite::ExpectAllFieldsSet(message3);
@@ -169,15 +208,14 @@
   }
 }
 
-TEST(Lite, AllLite2) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite2) {
   {
     protobuf_unittest::TestAllExtensionsLite message, message2, message3;
     TestUtilLite::ExpectExtensionsClear(message);
     TestUtilLite::SetAllExtensions(&message);
-    message2.CopyFrom(message);
-    std::string extensions_data = message.SerializeAsString();
-    message3.ParseFromString(extensions_data);
+    message2 = message;
+    TypeParam extensions_data = SerializeAs<TypeParam>(message);
+    ParseFrom(extensions_data, message3);
     TestUtilLite::ExpectAllExtensionsSet(message);
     TestUtilLite::ExpectAllExtensionsSet(message2);
     TestUtilLite::ExpectAllExtensionsSet(message3);
@@ -188,16 +226,16 @@
   }
 }
 
-TEST(Lite, AllLite3) {
-  std::string data, packed_data;
+TYPED_TEST(LiteTest, AllLite3) {
+  TypeParam data, packed_data;
 
   {
     protobuf_unittest::TestPackedTypesLite message, message2, message3;
     TestUtilLite::ExpectPackedClear(message);
     TestUtilLite::SetPackedFields(&message);
-    message2.CopyFrom(message);
-    packed_data = message.SerializeAsString();
-    message3.ParseFromString(packed_data);
+    message2 = message;
+    packed_data = SerializeAs<TypeParam>(message);
+    ParseFrom(packed_data, message3);
     TestUtilLite::ExpectPackedFieldsSet(message);
     TestUtilLite::ExpectPackedFieldsSet(message2);
     TestUtilLite::ExpectPackedFieldsSet(message3);
@@ -211,10 +249,10 @@
     protobuf_unittest::TestPackedExtensionsLite message, message2, message3;
     TestUtilLite::ExpectPackedExtensionsClear(message);
     TestUtilLite::SetPackedExtensions(&message);
-    message2.CopyFrom(message);
-    std::string packed_extensions_data = message.SerializeAsString();
+    message2 = message;
+    TypeParam packed_extensions_data = SerializeAs<TypeParam>(message);
     EXPECT_EQ(packed_extensions_data, packed_data);
-    message3.ParseFromString(packed_extensions_data);
+    ParseFrom(packed_extensions_data, message3);
     TestUtilLite::ExpectPackedExtensionsSet(message);
     TestUtilLite::ExpectPackedExtensionsSet(message2);
     TestUtilLite::ExpectPackedExtensionsSet(message3);
@@ -225,8 +263,8 @@
   }
 }
 
-TEST(Lite, AllLite5) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite5) {
+  TypeParam data;
 
   {
     // Test that if an optional or required message/group field appears multiple
@@ -260,10 +298,11 @@
 
 #undef ASSIGN_REPEATED_GROUP
 
-    std::string buffer;
-    generator.SerializeToString(&buffer);
+    TypeParam buffer;
+    buffer = SerializeAs<TypeParam>(generator);
+    //    generator.SerializeToString(&buffer);
     unittest::TestParsingMergeLite parsing_merge;
-    parsing_merge.ParseFromString(buffer);
+    ParseFrom(buffer, parsing_merge);
 
     // Required and optional fields should be merged.
     ExpectMessageMerged(parsing_merge.required_all_types());
@@ -282,8 +321,8 @@
   }
 }
 
-TEST(Lite, AllLite6) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite6) {
+  TypeParam data;
 
   // Test unknown fields support for lite messages.
   {
@@ -291,51 +330,48 @@
     protobuf_unittest::TestEmptyMessageLite empty_message;
     TestUtilLite::ExpectClear(message);
     TestUtilLite::SetAllFields(&message);
-    data = message.SerializeAsString();
-    ASSERT_TRUE(empty_message.ParseFromString(data));
-    data.clear();
-    data = empty_message.SerializeAsString();
-    EXPECT_TRUE(message2.ParseFromString(data));
-    data = message2.SerializeAsString();
+    data = SerializeAs<TypeParam>(message);
+    ASSERT_TRUE(ParseFrom(data, empty_message));
+    data = SerializeAs<TypeParam>(empty_message);
+    EXPECT_TRUE(ParseFrom(data, message2));
+    data = SerializeAs<TypeParam>(message2);
     TestUtilLite::ExpectAllFieldsSet(message2);
     message.Clear();
     TestUtilLite::ExpectClear(message);
   }
 }
 
-TEST(Lite, AllLite7) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite7) {
+  TypeParam data;
 
   {
     protobuf_unittest::TestAllExtensionsLite message, message2;
     protobuf_unittest::TestEmptyMessageLite empty_message;
     TestUtilLite::ExpectExtensionsClear(message);
     TestUtilLite::SetAllExtensions(&message);
-    data = message.SerializeAsString();
-    empty_message.ParseFromString(data);
-    data.clear();
+    data = SerializeAs<TypeParam>(message);
+    ParseFrom(data, empty_message);
     data = empty_message.SerializeAsString();
-    message2.ParseFromString(data);
-    data = message2.SerializeAsString();
+    ParseFrom(data, message2);
+    data = SerializeAs<TypeParam>(message2);
     TestUtilLite::ExpectAllExtensionsSet(message2);
     message.Clear();
     TestUtilLite::ExpectExtensionsClear(message);
   }
 }
 
-TEST(Lite, AllLite8) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite8) {
+  TypeParam data;
 
   {
     protobuf_unittest::TestPackedTypesLite message, message2;
     protobuf_unittest::TestEmptyMessageLite empty_message;
     TestUtilLite::ExpectPackedClear(message);
     TestUtilLite::SetPackedFields(&message);
-    data = message.SerializeAsString();
-    empty_message.ParseFromString(data);
-    data.clear();
-    data = empty_message.SerializeAsString();
-    message2.ParseFromString(data);
+    data = SerializeAs<TypeParam>(message);
+    ParseFrom(data, empty_message);
+    data = SerializeAs<TypeParam>(empty_message);
+    ParseFrom(data, message2);
     data = message2.SerializeAsString();
     TestUtilLite::ExpectPackedFieldsSet(message2);
     message.Clear();
@@ -343,57 +379,56 @@
   }
 }
 
-TEST(Lite, AllLite9) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite9) {
+  TypeParam data;
 
   {
     protobuf_unittest::TestPackedExtensionsLite message, message2;
     protobuf_unittest::TestEmptyMessageLite empty_message;
     TestUtilLite::ExpectPackedExtensionsClear(message);
     TestUtilLite::SetPackedExtensions(&message);
-    data = message.SerializeAsString();
-    empty_message.ParseFromString(data);
-    data.clear();
-    data = empty_message.SerializeAsString();
-    message2.ParseFromString(data);
-    data = message2.SerializeAsString();
+    data = SerializeAs<TypeParam>(message);
+    ParseFrom(data, empty_message);
+    data = SerializeAs<TypeParam>(empty_message);
+    ParseFrom(data, message2);
+    data = SerializeAs<TypeParam>(message2);
     TestUtilLite::ExpectPackedExtensionsSet(message2);
     message.Clear();
     TestUtilLite::ExpectPackedExtensionsClear(message);
   }
 }
 
-TEST(Lite, AllLite10) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite10) {
+  TypeParam data;
 
   {
     // Test Unknown fields swap
     protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2;
-    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
+    SetAllTypesInEmptyMessageUnknownFields<TypeParam>(&empty_message);
     SetSomeTypesInEmptyMessageUnknownFields(&empty_message2);
-    data = empty_message.SerializeAsString();
-    std::string data2 = empty_message2.SerializeAsString();
+    data = SerializeAs<TypeParam>(empty_message);
+    auto data2 = SerializeAs<TypeParam>(empty_message2);
     empty_message.Swap(&empty_message2);
-    EXPECT_EQ(data, empty_message2.SerializeAsString());
-    EXPECT_EQ(data2, empty_message.SerializeAsString());
+    EXPECT_EQ(data, SerializeAs<TypeParam>(empty_message2));
+    EXPECT_EQ(data2, SerializeAs<TypeParam>(empty_message));
   }
 }
 
-TEST(Lite, AllLite11) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite11) {
+  TypeParam data;
 
   {
     // Test unknown fields swap with self
     protobuf_unittest::TestEmptyMessageLite empty_message;
-    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
-    data = empty_message.SerializeAsString();
+    SetAllTypesInEmptyMessageUnknownFields<TypeParam>(&empty_message);
+    data = SerializeAs<TypeParam>(empty_message);
     empty_message.Swap(&empty_message);
     EXPECT_EQ(data, empty_message.SerializeAsString());
   }
 }
 
-TEST(Lite, AllLite12) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite12) {
+  TypeParam data;
 
   {
     // Test MergeFrom with unknown fields
@@ -406,24 +441,25 @@
     message2.add_repeated_int64(202);
     message2.set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ);
 
-    data = message.SerializeAsString();
-    empty_message.ParseFromString(data);
+    data = SerializeAs<TypeParam>(message);
+    ParseFrom(data, empty_message);
     data = message2.SerializeAsString();
-    empty_message2.ParseFromString(data);
+    ParseFrom(data, empty_message2);
     message.MergeFrom(message2);
     empty_message.MergeFrom(empty_message2);
 
-    data = empty_message.SerializeAsString();
-    message2.ParseFromString(data);
+    data = SerializeAs<TypeParam>(empty_message);
+    ParseFrom(data, message2);
     // We do not compare the serialized output of a normal message and a lite
     // message because the order of fields do not match. We convert lite message
     // back into normal message, then compare.
-    EXPECT_EQ(message.SerializeAsString(), message2.SerializeAsString());
+    EXPECT_EQ(SerializeAs<TypeParam>(message),
+              SerializeAs<TypeParam>(message2));
   }
 }
 
-TEST(Lite, AllLite13) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite13StringStream) {
+  TypeParam data;
 
   {
     // Test unknown enum value
@@ -442,18 +478,41 @@
       coded_output.WriteVarint32(20);
     }
     message.ParseFromString(buffer);
-    data = message.SerializeAsString();
+    data = SerializeAs<TypeParam>(message);
     EXPECT_EQ(data, buffer);
   }
 }
 
-TEST(Lite, AllLite14) {
-  std::string data;
+TYPED_TEST(LiteTest, AllLite13CordStream) {
+  TypeParam data;
 
   {
+    // Test unknown enum value
+    protobuf_unittest::TestAllTypesLite message;
+    io::CordOutputStream output_stream;
+    {
+      io::CodedOutputStream coded_output(&output_stream);
+      internal::WireFormatLite::WriteTag(
+          protobuf_unittest::TestAllTypesLite::kOptionalNestedEnumFieldNumber,
+          internal::WireFormatLite::WIRETYPE_VARINT, &coded_output);
+      coded_output.WriteVarint32(10);
+      internal::WireFormatLite::WriteTag(
+          protobuf_unittest::TestAllTypesLite::kRepeatedNestedEnumFieldNumber,
+          internal::WireFormatLite::WIRETYPE_VARINT, &coded_output);
+      coded_output.WriteVarint32(20);
+    }
+    absl::Cord buffer = output_stream.Consume();
+    message.ParseFromCord(buffer);
+    data = SerializeAs<TypeParam>(message);
+    EXPECT_EQ(data, buffer);
+  }
+}
+
+TYPED_TEST(LiteTest, AllLite14) {
+  {
     // Test Clear with unknown fields
     protobuf_unittest::TestEmptyMessageLite empty_message;
-    SetAllTypesInEmptyMessageUnknownFields(&empty_message);
+    SetAllTypesInEmptyMessageUnknownFields<TypeParam>(&empty_message);
     empty_message.Clear();
     EXPECT_EQ(0, empty_message.unknown_fields().size());
   }
@@ -461,9 +520,7 @@
 
 // Tests for map lite =============================================
 
-TEST(Lite, AllLite15) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite15) {
   {
     // Accessors
     protobuf_unittest::TestMapLite message;
@@ -476,9 +533,7 @@
   }
 }
 
-TEST(Lite, AllLite16) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite16) {
   {
     // SetMapFieldsInitialized
     protobuf_unittest::TestMapLite message;
@@ -488,9 +543,7 @@
   }
 }
 
-TEST(Lite, AllLite17) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite17) {
   {
     // Clear
     protobuf_unittest::TestMapLite message;
@@ -501,9 +554,7 @@
   }
 }
 
-TEST(Lite, AllLite18) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite18) {
   {
     // ClearMessageMap
     protobuf_unittest::TestMessageMapLite message;
@@ -513,26 +564,22 @@
   }
 }
 
-TEST(Lite, AllLite19) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite19) {
   {
     // CopyFrom
     protobuf_unittest::TestMapLite message1, message2;
 
     MapLiteTestUtil::SetMapFields(&message1);
-    message2.CopyFrom(message1);
+    message2.CopyFrom(message1);  // NOLINT
     MapLiteTestUtil::ExpectMapFieldsSet(message2);
 
     // Copying from self should be a no-op.
-    message2.CopyFrom(message2);
+    message2.CopyFrom(message2);  // NOLINT
     MapLiteTestUtil::ExpectMapFieldsSet(message2);
   }
 }
 
-TEST(Lite, AllLite20) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite20) {
   {
     // CopyFromMessageMap
     protobuf_unittest::TestMessageMapLite message1, message2;
@@ -540,7 +587,7 @@
     (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
     (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
 
-    message1.CopyFrom(message2);
+    message1.CopyFrom(message2);  // NOLINT
 
     // Checks repeated field is overwritten.
     EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
@@ -548,9 +595,7 @@
   }
 }
 
-TEST(Lite, AllLite21) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite21) {
   {
     // SwapWithEmpty
     protobuf_unittest::TestMapLite message1, message2;
@@ -565,9 +610,7 @@
   }
 }
 
-TEST(Lite, AllLite22) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite22) {
   {
     // SwapWithSelf
     protobuf_unittest::TestMapLite message;
@@ -580,9 +623,7 @@
   }
 }
 
-TEST(Lite, AllLite23) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite23) {
   {
     // SwapWithOther
     protobuf_unittest::TestMapLite message1, message2;
@@ -597,9 +638,7 @@
   }
 }
 
-TEST(Lite, AllLite24) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite24) {
   {
     // CopyConstructor
     protobuf_unittest::TestMapLite message1;
@@ -610,9 +649,7 @@
   }
 }
 
-TEST(Lite, AllLite25) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite25) {
   {
     // CopyAssignmentOperator
     protobuf_unittest::TestMapLite message1;
@@ -628,9 +665,7 @@
   }
 }
 
-TEST(Lite, AllLite26) {
-  std::string data;
-
+TEST(LiteBasicTest, AllLite26) {
   {
     // NonEmptyMergeFrom
     protobuf_unittest::TestMapLite message1, message2;
@@ -650,9 +685,7 @@
   }
 }
 
-TEST(Lite, AllLite27) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite27) {
   {
     // MergeFromMessageMap
     protobuf_unittest::TestMessageMapLite message1, message2;
@@ -668,9 +701,7 @@
   }
 }
 
-TEST(Lite, AllLite28) {
-  std::string data;
-
+TEST(LiteStringTest, AllLite28) {
   {
     // Test the generated SerializeWithCachedSizesToArray()
     protobuf_unittest::TestMapLite message1, message2;
@@ -686,9 +717,7 @@
   }
 }
 
-TEST(Lite, AllLite29) {
-  std::string data;
-
+TEST(LiteStreamTest, AllLite29) {
   {
     // Test the generated SerializeWithCachedSizes()
     protobuf_unittest::TestMapLite message1, message2;
@@ -710,9 +739,7 @@
 }
 
 
-TEST(Lite, AllLite32) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite32) {
   {
     // Proto2UnknownEnum
     protobuf_unittest::TestEnumMapPlusExtraLite from;
@@ -720,21 +747,20 @@
         protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE;
     (*from.mutable_unknown_map_field())[0] =
         protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE;
-    std::string data;
-    from.SerializeToString(&data);
+    TypeParam data;
+    data = SerializeAs<TypeParam>(from);
 
     protobuf_unittest::TestEnumMapLite to;
-    EXPECT_TRUE(to.ParseFromString(data));
+    EXPECT_TRUE(ParseFrom(data, to));
     EXPECT_EQ(0, to.unknown_map_field().size());
     EXPECT_FALSE(to.mutable_unknown_fields()->empty());
     ASSERT_EQ(1, to.known_map_field().size());
     EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE,
               to.known_map_field().at(0));
 
-    data.clear();
     from.Clear();
-    to.SerializeToString(&data);
-    EXPECT_TRUE(from.ParseFromString(data));
+    data = SerializeAs<TypeParam>(to);
+    EXPECT_TRUE(ParseFrom(data, from));
     ASSERT_EQ(1, from.known_map_field().size());
     EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE,
               from.known_map_field().at(0));
@@ -744,9 +770,7 @@
   }
 }
 
-TEST(Lite, AllLite33) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite33) {
   {
     // StandardWireFormat
     protobuf_unittest::TestMapLite message;
@@ -758,9 +782,7 @@
   }
 }
 
-TEST(Lite, AllLite34) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite34) {
   {
     // UnorderedWireFormat
     protobuf_unittest::TestMapLite message;
@@ -776,7 +798,7 @@
   }
 }
 
-TEST(Lite, AllLite35) {
+TYPED_TEST(LiteTest, AllLite35) {
   std::string data;
 
   {
@@ -792,7 +814,7 @@
   }
 }
 
-TEST(Lite, AllLite36) {
+TYPED_TEST(LiteTest, AllLite36) {
   std::string data;
 
   {
@@ -808,9 +830,7 @@
   }
 }
 
-TEST(Lite, AllLite37) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite37) {
   {
     // MissedKeyWireFormat
     protobuf_unittest::TestMapLite message;
@@ -826,7 +846,7 @@
   }
 }
 
-TEST(Lite, AllLite38) {
+TYPED_TEST(LiteTest, AllLite38) {
   std::string data;
 
   {
@@ -844,9 +864,7 @@
   }
 }
 
-TEST(Lite, AllLite39) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite39) {
   {
     // UnknownFieldWireFormat
     protobuf_unittest::TestMapLite message;
@@ -860,9 +878,7 @@
   }
 }
 
-TEST(Lite, AllLite40) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite40) {
   {
     // CorruptedWireFormat
     protobuf_unittest::TestMapLite message;
@@ -874,9 +890,7 @@
   }
 }
 
-TEST(Lite, AllLite41) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite41) {
   {
     // IsInitialized
     protobuf_unittest::TestRequiredMessageMapLite map_message;
@@ -893,9 +907,7 @@
   }
 }
 
-TEST(Lite, AllLite42) {
-  std::string data;
-
+TYPED_TEST(LiteTest, AllLite42) {
   {
     // Check that adding more values to enum does not corrupt message
     // when passed through an old client.
@@ -926,7 +938,7 @@
 
 // Test that when parsing a oneof, we can successfully clear whatever already
 // happened to be stored in the oneof.
-TEST(Lite, AllLite43) {
+TYPED_TEST(LiteTest, AllLite43) {
   protobuf_unittest::TestOneofParsingLite message1;
 
   message1.set_oneof_int32(17);
@@ -970,7 +982,7 @@
 // Verify that we can successfully parse fields of various types within oneof
 // fields. We also verify that we can parse the same data twice into the same
 // message.
-TEST(Lite, AllLite44) {
+TYPED_TEST(LiteTest, AllLite44) {
   // Int32
   {
     protobuf_unittest::TestOneofParsingLite original;
@@ -1054,7 +1066,7 @@
   std::cout << "PASS" << std::endl;
 }
 
-TEST(Lite, AllLite45) {
+TYPED_TEST(LiteTest, AllLite45) {
   // Test unknown fields are not discarded upon parsing.
   std::string data = "\20\1";  // varint 1 with field number 2
 
@@ -1076,7 +1088,7 @@
 // unpacked) state we expect. These tests specifically check for that issue by
 // making sure we can parse repeated fields when the tag is higher than we would
 // expect.
-TEST(Lite, AllLite46) {
+TYPED_TEST(LiteTest, AllLite46) {
   protobuf_unittest::PackedInt32 packed;
   packed.add_repeated_int32(42);
   std::string serialized;
@@ -1088,7 +1100,7 @@
   EXPECT_EQ(42, non_packed.repeated_int32(0));
 }
 
-TEST(Lite, AllLite47) {
+TYPED_TEST(LiteTest, AllLite47) {
   protobuf_unittest::NonPackedFixed32 non_packed;
   non_packed.add_repeated_fixed32(42);
   std::string serialized;
@@ -1100,7 +1112,7 @@
   EXPECT_EQ(42, packed.repeated_fixed32(0));
 }
 
-TEST(Lite, MapCrash) {
+TYPED_TEST(LiteTest, MapCrash) {
   // See b/113635730
   Arena arena;
   auto msg = Arena::CreateMessage<protobuf_unittest::TestMapLite>(&arena);
@@ -1114,7 +1126,7 @@
       "\202\1\15\10\1\200\200\200\200\200\200\200\200\200\200\1"));
 }
 
-TEST(Lite, CorrectEnding) {
+TYPED_TEST(LiteTest, CorrectEnding) {
   protobuf_unittest::TestAllTypesLite msg;
   {
     // All proto wireformat parsers should act the same on parsing data in as
@@ -1144,7 +1156,7 @@
   }
 }
 
-TEST(Lite, DebugString) {
+TYPED_TEST(LiteTest, DebugString) {
   protobuf_unittest::TestAllTypesLite message1, message2;
   EXPECT_TRUE(absl::StartsWith(message1.DebugString(), "MessageLite at 0x"));
   EXPECT_TRUE(absl::StartsWith(message2.DebugString(), "MessageLite at 0x"));
@@ -1159,7 +1171,7 @@
   EXPECT_NE(message1.DebugString(), message2.DebugString());
 }
 
-TEST(Lite, EnumValueToName) {
+TYPED_TEST(LiteTest, EnumValueToName) {
   EXPECT_EQ("FOREIGN_LITE_FOO", protobuf_unittest::ForeignEnumLite_Name(
                                     protobuf_unittest::FOREIGN_LITE_FOO));
   EXPECT_EQ("FOREIGN_LITE_BAR", protobuf_unittest::ForeignEnumLite_Name(
@@ -1170,7 +1182,7 @@
   EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(999));
 }
 
-TEST(Lite, NestedEnumValueToName) {
+TYPED_TEST(LiteTest, NestedEnumValueToName) {
   EXPECT_EQ("FOO", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(
                        protobuf_unittest::TestAllTypesLite::FOO));
   EXPECT_EQ("BAR", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(
@@ -1181,7 +1193,7 @@
   EXPECT_EQ("", protobuf_unittest::TestAllTypesLite::NestedEnum_Name(999));
 }
 
-TEST(Lite, EnumNameToValue) {
+TYPED_TEST(LiteTest, EnumNameToValue) {
   protobuf_unittest::ForeignEnumLite value;
 
   ASSERT_TRUE(
@@ -1203,7 +1215,7 @@
   EXPECT_FALSE(protobuf_unittest::ForeignEnumLite_Parse("G", &value));
 }
 
-TEST(Lite, NestedEnumNameToValue) {
+TYPED_TEST(LiteTest, NestedEnumNameToValue) {
   protobuf_unittest::TestAllTypesLite::NestedEnum value;
 
   ASSERT_TRUE(
@@ -1227,7 +1239,7 @@
       protobuf_unittest::TestAllTypesLite::NestedEnum_Parse("G", &value));
 }
 
-TEST(Lite, AliasedEnum) {
+TYPED_TEST(LiteTest, AliasedEnum) {
   // Enums with allow_alias = true can have multiple entries with the same
   // value.
   EXPECT_EQ("FOO1", protobuf_unittest::DupEnum::TestEnumWithDupValueLite_Name(
@@ -1254,7 +1266,7 @@
 }
 
 
-TEST(Lite, CodedInputStreamRollback) {
+TEST(LiteBasicTest, CodedInputStreamRollback) {
   {
     protobuf_unittest::TestAllTypesLite m;
     m.set_optional_bytes(std::string(30, 'a'));
@@ -1332,5 +1344,6 @@
   }
 }
 
+}  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 5e0ab8a..fc0f56a 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -36,6 +36,7 @@
 #include "google/protobuf/message_lite.h"
 
 #include <climits>
+#include <cstddef>
 #include <cstdint>
 #include <istream>
 #include <ostream>
@@ -47,10 +48,12 @@
 #include "google/protobuf/stubs/logging.h"
 #include "google/protobuf/stubs/logging.h"
 #include "absl/strings/cord.h"
+#include "absl/strings/cord_buffer.h"
 #include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
+#include "absl/types/optional.h"
 #include "google/protobuf/io/coded_stream.h"
 #include "google/protobuf/io/zero_copy_stream.h"
 #include "google/protobuf/io/zero_copy_stream_impl.h"
@@ -200,6 +203,9 @@
 
   bool aliasing_enabled() { return cis_->aliasing_enabled_; }
 
+  bool ReadCord(absl::Cord* cord, int count) final {
+    return cis_->ReadCord(cord, count);
+  }
  private:
   io::CodedInputStream* cis_;
 };
@@ -317,6 +323,43 @@
 }
 
 
+namespace internal {
+
+template <>
+struct SourceWrapper<absl::Cord> {
+  explicit SourceWrapper(const absl::Cord* c) : cord(c) {}
+  template <bool alias>
+  bool MergeInto(MessageLite* msg, MessageLite::ParseFlags parse_flags) const {
+    absl::optional<absl::string_view> flat = cord->TryFlat();
+    if (flat && flat->size() <= ParseContext::kMaxCordBytesToCopy) {
+      return MergeFromImpl<alias>(*flat, msg, parse_flags);
+    } else {
+      io::CordInputStream input(cord);
+      return MergeFromImpl<alias>(&input, msg, parse_flags);
+    }
+  }
+
+  const absl::Cord* const cord;
+};
+
+}  // namespace internal
+
+bool MessageLite::MergeFromCord(const absl::Cord& cord) {
+  return ParseFrom<kMerge>(internal::SourceWrapper<absl::Cord>(&cord));
+}
+
+bool MessageLite::MergePartialFromCord(const absl::Cord& cord) {
+  return ParseFrom<kMergePartial>(internal::SourceWrapper<absl::Cord>(&cord));
+}
+
+bool MessageLite::ParseFromCord(const absl::Cord& cord) {
+  return ParseFrom<kParse>(internal::SourceWrapper<absl::Cord>(&cord));
+}
+
+bool MessageLite::ParsePartialFromCord(const absl::Cord& cord) {
+  return ParseFrom<kParsePartial>(internal::SourceWrapper<absl::Cord>(&cord));
+}
+
 // ===================================================================
 
 inline uint8_t* SerializeToArrayImpl(const MessageLite& msg, uint8_t* target,
@@ -498,6 +541,78 @@
   return output;
 }
 
+bool MessageLite::AppendToCord(absl::Cord* output) const {
+  GOOGLE_ABSL_DCHECK(IsInitialized())
+      << InitializationErrorMessage("serialize", *this);
+  return AppendPartialToCord(output);
+}
+
+bool MessageLite::AppendPartialToCord(absl::Cord* output) const {
+  // For efficiency, we'd like to pass a size hint to CordOutputStream with
+  // the exact total size expected.
+  const size_t size = ByteSizeLong();
+  const size_t total_size = size + output->size();
+  if (size > INT_MAX) {
+    GOOGLE_ABSL_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB.";
+    return false;
+  }
+
+
+  // Allocate a CordBuffer (which may utilize private capacity in 'output').
+  absl::CordBuffer buffer = output->GetAppendBuffer(size);
+  absl::Span<char> available = buffer.available();
+  auto target = reinterpret_cast<uint8_t*>(available.data());
+  if (available.size() >= size) {
+    // Use EpsCopyOutputStream with full available capacity, as serialization
+    // may in the future use the extra slop bytes if available.
+    io::EpsCopyOutputStream out(
+        target, static_cast<int>(available.size()),
+        io::CodedOutputStream::IsDefaultSerializationDeterministic());
+    auto res = _InternalSerialize(target, &out);
+    GOOGLE_ABSL_DCHECK_EQ(res, target + size);
+    buffer.IncreaseLengthBy(size);
+    output->Append(std::move(buffer));
+    GOOGLE_ABSL_DCHECK_EQ(output->size(), total_size);
+    return true;
+  }
+
+  // Donate the buffer to the CordOutputStream with length := capacity.
+  // This follows the eager `EpsCopyOutputStream` initialization logic.
+  buffer.SetLength(buffer.capacity());
+  io::CordOutputStream output_stream(std::move(*output), std::move(buffer),
+                                     total_size);
+  io::EpsCopyOutputStream out(
+      target, static_cast<int>(available.size()), &output_stream,
+      io::CodedOutputStream::IsDefaultSerializationDeterministic(), &target);
+  target = _InternalSerialize(target, &out);
+  out.Trim(target);
+  if (out.HadError()) return false;
+  *output = output_stream.Consume();
+  GOOGLE_ABSL_DCHECK_EQ(output->size(), total_size);
+  return true;
+}
+
+bool MessageLite::SerializeToCord(absl::Cord* output) const {
+  output->Clear();
+  return AppendToCord(output);
+}
+
+bool MessageLite::SerializePartialToCord(absl::Cord* output) const {
+  output->Clear();
+  return AppendPartialToCord(output);
+}
+
+absl::Cord MessageLite::SerializeAsCord() const {
+  absl::Cord output;
+  if (!AppendToCord(&output)) output.Clear();
+  return output;
+}
+
+absl::Cord MessageLite::SerializePartialAsCord() const {
+  absl::Cord output;
+  if (!AppendPartialToCord(&output)) output.Clear();
+  return output;
+}
 
 namespace internal {
 
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 7f266b3..fade4bb 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -49,6 +49,7 @@
 #include "google/protobuf/port.h"
 #include "absl/base/call_once.h"
 #include "google/protobuf/stubs/logging.h"
+#include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 #include "google/protobuf/explicitly_constructed.h"
 #include "google/protobuf/io/coded_stream.h"
@@ -371,6 +372,36 @@
   // Like AppendToString(), but allows missing required fields.
   bool AppendPartialToString(std::string* output) const;
 
+  // Reads a protocol buffer from a Cord and merges it into this message.
+  bool MergeFromCord(const absl::Cord& cord);
+  // Like MergeFromCord(), but accepts messages that are missing
+  // required fields.
+  bool MergePartialFromCord(const absl::Cord& cord);
+  // Parse a protocol buffer contained in a Cord.
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCord(const absl::Cord& cord);
+  // Like ParseFromCord(), but accepts messages that are missing
+  // required fields.
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCord(
+      const absl::Cord& cord);
+
+  // Serialize the message and store it in the given Cord.  All required
+  // fields must be set.
+  bool SerializeToCord(absl::Cord* output) const;
+  // Like SerializeToCord(), but allows missing required fields.
+  bool SerializePartialToCord(absl::Cord* output) const;
+
+  // Make a Cord encoding the message. Is equivalent to calling
+  // SerializeToCord() on a Cord and using that.  Returns an empty
+  // Cord if SerializeToCord() would have returned an error.
+  absl::Cord SerializeAsCord() const;
+  // Like SerializeAsCord(), but allows missing required fields.
+  absl::Cord SerializePartialAsCord() const;
+
+  // Like SerializeToCord(), but appends to the data to the Cord's existing
+  // contents.  All required fields must be set.
+  bool AppendToCord(absl::Cord* output) const;
+  // Like AppendToCord(), but allows missing required fields.
+  bool AppendPartialToCord(absl::Cord* output) const;
 
   // Computes the serialized size of the message.  This recursively calls
   // ByteSizeLong() on all embedded messages.