Add new API to directly create a QuicheMemSlice from a string_view.

PiperOrigin-RevId: 742332252
diff --git a/quiche/common/platform/api/quiche_mem_slice.cc b/quiche/common/platform/api/quiche_mem_slice.cc
index 87a0ed2..59f891f 100644
--- a/quiche/common/platform/api/quiche_mem_slice.cc
+++ b/quiche/common/platform/api/quiche_mem_slice.cc
@@ -2,6 +2,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstring>
 #include <memory>
 #include <utility>
 
@@ -63,4 +64,13 @@
   done_callback_ = nullptr;
 }
 
+QuicheMemSlice QuicheMemSlice::Copy(absl::string_view data) {
+  if (data.empty()) {
+    return QuicheMemSlice();
+  }
+  auto buffer = std::make_unique<char[]>(data.size());
+  memcpy(buffer.get(), data.data(), data.size());
+  return QuicheMemSlice(std::move(buffer), data.size());
+}
+
 }  // namespace quiche
diff --git a/quiche/common/platform/api/quiche_mem_slice.h b/quiche/common/platform/api/quiche_mem_slice.h
index 4afe9c1..0cc2e0b 100644
--- a/quiche/common/platform/api/quiche_mem_slice.h
+++ b/quiche/common/platform/api/quiche_mem_slice.h
@@ -20,6 +20,10 @@
  public:
   using ReleaseCallback = SingleUseCallback<void(absl::string_view)>;
 
+  // Creates a QuicheMemSlice by allocating memory on heap and copying the
+  // specified bytes.
+  static QuicheMemSlice Copy(absl::string_view data);
+
   // Constructs a empty QuicheMemSlice with no underlying data.
   QuicheMemSlice() = default;
 
diff --git a/quiche/common/platform/api/quiche_mem_slice_test.cc b/quiche/common/platform/api/quiche_mem_slice_test.cc
index 7eeceb2..c4a5ab5 100644
--- a/quiche/common/platform/api/quiche_mem_slice_test.cc
+++ b/quiche/common/platform/api/quiche_mem_slice_test.cc
@@ -128,6 +128,18 @@
   EXPECT_EQ(slice.length(), kTestString.length());
 }
 
+TEST_F(QuicheMemSliceTest, Copy) {
+  QuicheMemSlice slice = QuicheMemSlice::Copy("test");
+  EXPECT_EQ(slice.AsStringView(), "test");
+}
+
+TEST_F(QuicheMemSliceTest, CopyEmpty) {
+  QuicheMemSlice slice = QuicheMemSlice::Copy("");
+  EXPECT_TRUE(slice.empty());
+  EXPECT_TRUE(slice.data() == nullptr);
+  EXPECT_EQ(slice.length(), 0u);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quiche
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h
index d57bc83..b3e8790 100644
--- a/quiche/quic/test_tools/quic_test_utils.h
+++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -1651,7 +1651,9 @@
 
 // Creates a MemSlice using a singleton trivial buffer allocator.  Performs a
 // copy.
-quiche::QuicheMemSlice MemSliceFromString(absl::string_view data);
+// TODO: remove once all uses are replaced with QuicheMemSlice::Copy.
+[[deprecated]] quiche::QuicheMemSlice MemSliceFromString(
+    absl::string_view data);
 
 // Used to compare ReceivedPacketInfo.
 MATCHER_P(ReceivedPacketInfoEquals, info, "") {