Use absl::Span-based version WriteBodySlices() in GFE.

This should not change any functional behavior; however, this does add an extra copy and potentially an extra allocation of a memslice vector.

Protected by FLAGS_quic_restart_flag_quic_use_new_mem_slice_span.

PiperOrigin-RevId: 378499167
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index 0ef85dc..0c08938 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -454,6 +454,24 @@
   return WriteMemSlices(slices, fin);
 }
 
+QuicConsumedData QuicSpdyStream::WriteBodySlices(
+    absl::Span<QuicMemSlice> slices,
+    bool fin) {
+  if (!VersionUsesHttp3(transport_version()) || slices.empty()) {
+    return WriteMemSlices(slices, fin);
+  }
+
+  QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
+  const QuicByteCount data_size = MemSliceSpanTotalSize(slices);
+  if (!WriteDataFrameHeader(data_size, /*force_write=*/false)) {
+    return {0, false};
+  }
+
+  QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
+                  << " is writing DATA frame payload of length " << data_size;
+  return WriteMemSlices(slices, fin);
+}
+
 size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) {
   QUICHE_DCHECK(FinishedReadingHeaders());
   if (!VersionUsesHttp3(transport_version())) {
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h
index 160ed56..4f962ce 100644
--- a/quic/core/http/quic_spdy_stream.h
+++ b/quic/core/http/quic_spdy_stream.h
@@ -18,6 +18,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/span.h"
 #include "quic/core/http/http_decoder.h"
 #include "quic/core/http/http_encoder.h"
 #include "quic/core/http/quic_header_list.h"
@@ -159,6 +160,7 @@
   // Does the same thing as WriteOrBufferBody except this method takes
   // memslicespan as the data input. Right now it only calls WriteMemSlices.
   QuicConsumedData WriteBodySlices(QuicMemSliceSpan slices, bool fin);
+  QuicConsumedData WriteBodySlices(absl::Span<QuicMemSlice> slices, bool fin);
 
   // Marks the trailers as consumed. This applies to the case where this object
   // receives headers and trailers as QuicHeaderLists via calls to
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc
index b34506c..65c9ced 100644
--- a/quic/core/quic_utils.cc
+++ b/quic/core/quic_utils.cc
@@ -21,6 +21,7 @@
 #include "quic/platform/api/quic_bug_tracker.h"
 #include "quic/platform/api/quic_flag_utils.h"
 #include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_mem_slice.h"
 #include "common/platform/api/quiche_logging.h"
 #include "common/platform/api/quiche_prefetch.h"
 #include "common/quiche_endian.h"
@@ -714,5 +715,13 @@
          QuicUtils::IsClientInitiatedStreamId(version.transport_version, id);
 }
 
+QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span) {
+  QuicByteCount total = 0;
+  for (const QuicMemSlice& slice : span) {
+    total += slice.length();
+  }
+  return total;
+}
+
 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
 }  // namespace quic
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h
index 8530954..6fcc5f2 100644
--- a/quic/core/quic_utils.h
+++ b/quic/core/quic_utils.h
@@ -13,6 +13,7 @@
 
 #include "absl/numeric/int128.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/span.h"
 #include "quic/core/crypto/quic_random.h"
 #include "quic/core/frames/quic_frame.h"
 #include "quic/core/quic_connection_id.h"
@@ -21,6 +22,7 @@
 #include "quic/core/quic_versions.h"
 #include "quic/platform/api/quic_export.h"
 #include "quic/platform/api/quic_iovec.h"
+#include "quic/platform/api/quic_mem_slice.h"
 #include "quic/platform/api/quic_socket_address.h"
 
 namespace quic {
@@ -249,6 +251,8 @@
 bool IsValidWebTransportSessionId(WebTransportSessionId id,
                                   ParsedQuicVersion transport_version);
 
+QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span);
+
 template <typename Mask>
 class QUIC_EXPORT_PRIVATE BitMask {
  public: