Make HttpEncoder::SerializeDataFrameHeader() return a QuicBuffer

This helps avoid an allocation and a copy in QuicSpdyStream::WriteMemSlices().

PiperOrigin-RevId: 377540689
diff --git a/quic/core/http/http_decoder_test.cc b/quic/core/http/http_decoder_test.cc
index 05d580e..3f7fb02 100644
--- a/quic/core/http/http_decoder_test.cc
+++ b/quic/core/http/http_decoder_test.cc
@@ -564,10 +564,8 @@
   InSequence s;
   // A large input that will occupy more than 1 byte in the length field.
   std::string input(2048, 'x');
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(input.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      input.length(), SimpleBufferAllocator::Get());
   // Partially send only 1 byte of the header to process.
   EXPECT_EQ(1u, decoder_.ProcessInput(header.data(), 1));
   EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -575,8 +573,8 @@
 
   // Send the rest of the header.
   EXPECT_CALL(visitor_, OnDataFrameStart(3, input.length()));
-  EXPECT_EQ(header_length - 1,
-            decoder_.ProcessInput(header.data() + 1, header_length - 1));
+  EXPECT_EQ(header.size() - 1,
+            decoder_.ProcessInput(header.data() + 1, header.size() - 1));
   EXPECT_THAT(decoder_.error(), IsQuicNoError());
   EXPECT_EQ("", decoder_.error_detail());
 
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 2fbc238..1e4b469 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -34,23 +34,23 @@
 }  // namespace
 
 // static
-QuicByteCount HttpEncoder::SerializeDataFrameHeader(
+QuicBuffer HttpEncoder::SerializeDataFrameHeader(
     QuicByteCount payload_length,
-    std::unique_ptr<char[]>* output) {
+    QuicBufferAllocator* allocator) {
   QUICHE_DCHECK_NE(0u, payload_length);
   QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(payload_length) +
                                 QuicDataWriter::GetVarInt62Len(
                                     static_cast<uint64_t>(HttpFrameType::DATA));
 
-  output->reset(new char[header_length]);
-  QuicDataWriter writer(header_length, output->get());
+  QuicBuffer header(allocator, header_length);
+  QuicDataWriter writer(header.size(), header.data());
 
   if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
-    return header_length;
+    return header;
   }
   QUIC_DLOG(ERROR)
       << "Http encoder failed when attempting to serialize data frame header.";
-  return 0;
+  return QuicBuffer();
 }
 
 // static
diff --git a/quic/core/http/http_encoder.h b/quic/core/http/http_encoder.h
index 0a8aa84..dc48bb0 100644
--- a/quic/core/http/http_encoder.h
+++ b/quic/core/http/http_encoder.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include "quic/core/http/http_frames.h"
+#include "quic/core/quic_buffer_allocator.h"
 #include "quic/core/quic_error_codes.h"
 #include "quic/core/quic_types.h"
 #include "quic/platform/api/quic_export.h"
@@ -21,11 +22,10 @@
  public:
   HttpEncoder() = delete;
 
-  // Serializes a DATA frame header into a new buffer stored in |output|.
-  // Returns the length of the buffer on success, or 0 otherwise.
-  static QuicByteCount SerializeDataFrameHeader(
-      QuicByteCount payload_length,
-      std::unique_ptr<char[]>* output);
+  // Serializes a DATA frame header into a QuicBuffer; returns said QuicBuffer
+  // on success, empty buffer otherwise.
+  static QuicBuffer SerializeDataFrameHeader(QuicByteCount payload_length,
+                                             QuicBufferAllocator* allocator);
 
   // Serializes a HEADERS frame header into a new buffer stored in |output|.
   // Returns the length of the buffer on success, or 0 otherwise.
diff --git a/quic/core/http/http_encoder_test.cc b/quic/core/http/http_encoder_test.cc
index 66e988f..3032cd6 100644
--- a/quic/core/http/http_encoder_test.cc
+++ b/quic/core/http/http_encoder_test.cc
@@ -5,6 +5,7 @@
 #include "quic/core/http/http_encoder.h"
 
 #include "absl/base/macros.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
 #include "quic/platform/api/quic_flags.h"
 #include "quic/platform/api/quic_test.h"
 #include "quic/test_tools/quic_test_utils.h"
@@ -14,16 +15,15 @@
 namespace test {
 
 TEST(HttpEncoderTest, SerializeDataFrameHeader) {
-  std::unique_ptr<char[]> buffer;
-  uint64_t length =
-      HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
+  QuicBuffer buffer = HttpEncoder::SerializeDataFrameHeader(
+      /* payload_length = */ 5, SimpleBufferAllocator::Get());
   char output[] = {// type (DATA)
                    0x00,
                    // length
                    0x05};
-  EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
-  quiche::test::CompareCharArraysWithHexError("DATA", buffer.get(), length,
-                                              output, ABSL_ARRAYSIZE(output));
+  EXPECT_EQ(ABSL_ARRAYSIZE(output), buffer.size());
+  quiche::test::CompareCharArraysWithHexError(
+      "DATA", buffer.data(), buffer.size(), output, ABSL_ARRAYSIZE(output));
 }
 
 TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
diff --git a/quic/core/http/quic_receive_control_stream_test.cc b/quic/core/http/quic_receive_control_stream_test.cc
index 03f21d8..ec74af5 100644
--- a/quic/core/http/quic_receive_control_stream_test.cc
+++ b/quic/core/http/quic_receive_control_stream_test.cc
@@ -9,6 +9,7 @@
 #include "absl/strings/string_view.h"
 #include "quic/core/http/http_constants.h"
 #include "quic/core/qpack/qpack_header_table.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
 #include "quic/core/quic_types.h"
 #include "quic/core/quic_utils.h"
 #include "quic/test_tools/qpack/qpack_encoder_peer.h"
@@ -239,12 +240,11 @@
 
 TEST_P(QuicReceiveControlStreamTest, ReceiveWrongFrame) {
   // DATA frame header without payload.
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 2, &buffer);
-  std::string data = std::string(buffer.get(), header_length);
+  QuicBuffer data = HttpEncoder::SerializeDataFrameHeader(
+      /* payload_length = */ 2, SimpleBufferAllocator::Get());
 
-  QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
+  QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
+                        data.AsStringView());
   EXPECT_CALL(
       *connection_,
       CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _));
diff --git a/quic/core/http/quic_spdy_client_stream_test.cc b/quic/core/http/quic_spdy_client_stream_test.cc
index fa4943d..9043d0b 100644
--- a/quic/core/http/quic_spdy_client_stream_test.cc
+++ b/quic/core/http/quic_spdy_client_stream_test.cc
@@ -12,6 +12,7 @@
 #include "quic/core/crypto/null_encrypter.h"
 #include "quic/core/http/quic_spdy_client_session.h"
 #include "quic/core/http/spdy_utils.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
 #include "quic/core/quic_utils.h"
 #include "quic/platform/api/quic_logging.h"
 #include "quic/platform/api/quic_socket_address.h"
@@ -131,12 +132,10 @@
   auto headers = AsHeaderList(headers_);
   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
                               headers);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
   std::string data = VersionUsesHttp3(connection_->transport_version())
-                         ? header + body_
+                         ? absl::StrCat(header.AsStringView(), body_)
                          : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
@@ -160,12 +159,11 @@
   headers = AsHeaderList(headers_);
   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
                               headers);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data =
-      connection_->version().UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data = VersionUsesHttp3(connection_->transport_version())
+                         ? absl::StrCat(header.AsStringView(), body_)
+                         : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   // Make sure the 200 response got parsed correctly.
@@ -190,12 +188,11 @@
   headers = AsHeaderList(headers_);
   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
                               headers);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data =
-      connection_->version().UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data = VersionUsesHttp3(connection_->transport_version())
+                         ? absl::StrCat(header.AsStringView(), body_)
+                         : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   // Make sure the 200 response got parsed correctly.
@@ -222,12 +219,10 @@
   auto headers = AsHeaderList(headers_);
   stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
                               headers);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
   std::string data = VersionUsesHttp3(connection_->transport_version())
-                         ? header + body_
+                         ? absl::StrCat(header.AsStringView(), body_)
                          : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
@@ -247,12 +242,10 @@
   EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
   EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
   EXPECT_EQ(200, stream_->response_code());
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      large_body.length(), SimpleBufferAllocator::Get());
   std::string data = VersionUsesHttp3(connection_->transport_version())
-                         ? header + large_body
+                         ? absl::StrCat(header.AsStringView(), large_body)
                          : large_body;
   EXPECT_CALL(session_, WriteControlFrame(_, _));
   EXPECT_CALL(*connection_,
@@ -290,12 +283,10 @@
 
   // Now send the body, which should close the stream as the FIN has been
   // received, as well as all data.
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
   std::string data = VersionUsesHttp3(connection_->transport_version())
-                         ? header + body_
+                         ? absl::StrCat(header.AsStringView(), body_)
                          : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index 6ec48ca..9346be5 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -343,17 +343,16 @@
   }
 
   // Write frame header.
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(data.length(), &buffer);
+  const QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      data.length(),
+      spdy_session_->connection()->helper()->GetStreamSendBufferAllocator());
   unacked_frame_headers_offsets_.Add(
       send_buffer().stream_offset(),
-      send_buffer().stream_offset() + header_length);
+      send_buffer().stream_offset() + header.size());
   QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
                   << " is writing DATA frame header of length "
-                  << header_length;
-  WriteOrBufferData(absl::string_view(buffer.get(), header_length), false,
-                    nullptr);
+                  << header.size();
+  WriteOrBufferData(header.AsStringView(), false, nullptr);
 
   // Write body.
   QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
@@ -419,10 +418,10 @@
     return WriteMemSlices(slices, fin);
   }
 
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(slices.total_length(), &buffer);
-  if (!CanWriteNewDataAfterData(header_length)) {
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      slices.total_length(),
+      spdy_session_->connection()->helper()->GetStreamSendBufferAllocator());
+  if (!CanWriteNewDataAfterData(header.size())) {
     return {0, false};
   }
 
@@ -434,23 +433,14 @@
   QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
 
   // Write frame header.
-#if !defined(__ANDROID__)
-  struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
-#else
-  struct iovec header_iov = {static_cast<void*>(buffer.get()),
-                             static_cast<__kernel_size_t>(header_length)};
-#endif
-  QuicMemSliceStorage storage(
-      &header_iov, 1,
-      spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
-      GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
   unacked_frame_headers_offsets_.Add(
       send_buffer().stream_offset(),
-      send_buffer().stream_offset() + header_length);
+      send_buffer().stream_offset() + header.size());
   QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
                   << " is writing DATA frame header of length "
-                  << header_length;
-  WriteMemSlices(storage.ToSpan(), false);
+                  << header.size();
+  QuicMemSlice header_slice(std::move(header));
+  WriteMemSlices(QuicMemSliceSpan(&header_slice), false);
 
   // Write body.
   QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 8b814b8..57f3e4d 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -19,6 +19,7 @@
 #include "quic/core/http/spdy_utils.h"
 #include "quic/core/http/web_transport_http3.h"
 #include "quic/core/quic_connection.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
 #include "quic/core/quic_stream_sequencer_buffer.h"
 #include "quic/core/quic_utils.h"
 #include "quic/core/quic_versions.h"
@@ -475,12 +476,9 @@
   }
 
   std::string DataFrame(absl::string_view payload) {
-    std::unique_ptr<char[]> data_buffer;
-    QuicByteCount data_frame_header_length =
-        HttpEncoder::SerializeDataFrameHeader(payload.length(), &data_buffer);
-    absl::string_view data_frame_header(data_buffer.get(),
-                                        data_frame_header_length);
-    return absl::StrCat(data_frame_header, payload);
+    QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+        payload.length(), SimpleBufferAllocator::Get());
+    return absl::StrCat(header.AsStringView(), payload);
   }
 
   std::string UnknownFrame(uint64_t frame_type, absl::string_view payload) {
@@ -1005,11 +1003,10 @@
   std::string data;
 
   if (UsesHttp3()) {
-    std::unique_ptr<char[]> buffer;
-    header_length =
-        HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
-    std::string header = std::string(buffer.get(), header_length);
-    data = header + body;
+    QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+        body.length(), SimpleBufferAllocator::Get());
+    data = absl::StrCat(header.AsStringView(), body);
+    header_length = header.size();
   } else {
     data = body;
   }
@@ -1049,11 +1046,10 @@
   std::string data;
 
   if (UsesHttp3()) {
-    std::unique_ptr<char[]> buffer;
-    header_length =
-        HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
-    std::string header = std::string(buffer.get(), header_length);
-    data = header + body;
+    QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+        body.length(), SimpleBufferAllocator::Get());
+    data = absl::StrCat(header.AsStringView(), body);
+    header_length = header.size();
   } else {
     data = body;
   }
@@ -1115,16 +1111,13 @@
 
   if (UsesHttp3()) {
     body = std::string(kWindow / 4 - 2, 'a');
-    std::unique_ptr<char[]> buffer;
-    header_length =
-        HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
-    std::string header = std::string(buffer.get(), header_length);
-    data = header + body;
-    std::unique_ptr<char[]> buffer2;
-    QuicByteCount header_length2 =
-        HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer2);
-    std::string header2 = std::string(buffer2.get(), header_length2);
-    data2 = header2 + body2;
+    QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+        body.length(), SimpleBufferAllocator::Get());
+    data = absl::StrCat(header.AsStringView(), body);
+    header_length = header.size();
+    QuicBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
+        body.length(), SimpleBufferAllocator::Get());
+    data2 = absl::StrCat(header2.AsStringView(), body2);
   } else {
     body = std::string(kWindow / 4, 'a');
     data = body;
@@ -1595,8 +1588,9 @@
   std::string body(1024, 'x');  // 1 kB
   QuicByteCount header_length = 0;
   if (UsesHttp3()) {
-    std::unique_ptr<char[]> buf;
-    header_length = HttpEncoder::SerializeDataFrameHeader(body.length(), &buf);
+    header_length = HttpEncoder::SerializeDataFrameHeader(
+                        body.length(), SimpleBufferAllocator::Get())
+                        .size();
   }
 
   stream_->WriteOrBufferBody(body, false);
@@ -1939,30 +1933,26 @@
   stream_->WriteOrBufferBody(body, false);
   stream_->WriteOrBufferBody(body2, true);
 
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-
-  header_length =
-      HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer);
-  std::string header2 = std::string(buffer.get(), header_length);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body.length(), SimpleBufferAllocator::Get());
+  QuicBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
+      body2.length(), SimpleBufferAllocator::Get());
 
   EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
-  QuicStreamFrame frame(stream_->id(), false, 0, header + body);
+  QuicStreamFrame frame(stream_->id(), false, 0,
+                        absl::StrCat(header.AsStringView(), body));
   EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
                                      QuicTime::Zero()));
 
   EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
-  QuicStreamFrame frame2(stream_->id(), false, header.length() + body.length(),
-                         header2);
+  QuicStreamFrame frame2(stream_->id(), false, header.size() + body.length(),
+                         header2.AsStringView());
   EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
                                      QuicTime::Zero()));
 
   EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
   QuicStreamFrame frame3(stream_->id(), true,
-                         header.length() + body.length() + header2.length(),
-                         body2);
+                         header.size() + body.length() + header2.size(), body2);
   EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
                                      QuicTime::Zero()));
 
diff --git a/quic/core/quic_simple_buffer_allocator.h b/quic/core/quic_simple_buffer_allocator.h
index cbf73b3..c2a800d 100644
--- a/quic/core/quic_simple_buffer_allocator.h
+++ b/quic/core/quic_simple_buffer_allocator.h
@@ -12,6 +12,11 @@
 
 class QUIC_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
  public:
+  static SimpleBufferAllocator* Get() {
+    static SimpleBufferAllocator* singleton = new SimpleBufferAllocator();
+    return singleton;
+  }
+
   char* New(size_t size) override;
   char* New(size_t size, bool flag_enable) override;
   void Delete(char* buffer) override;
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 2542311..86aea67 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -16,6 +16,7 @@
 #include "quic/core/http/http_encoder.h"
 #include "quic/core/http/spdy_utils.h"
 #include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
 #include "quic/core/quic_types.h"
 #include "quic/core/quic_utils.h"
 #include "quic/platform/api/quic_expect_bug.h"
@@ -311,11 +312,10 @@
       .WillRepeatedly(
           Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
   stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data = UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data =
+      UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -330,11 +330,10 @@
           Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
 
   stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data = UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data =
+      UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -377,20 +376,20 @@
   EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
 
   stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data = UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data =
+      UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
 
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   // Content length is still 11.  This will register as an error and we won't
   // accept the bytes.
-  header_length =
-      HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
-  header = std::string(buffer.get(), header_length);
-  std::string data2 = UsesHttp3() ? header + large_body : large_body;
+  header = HttpEncoder::SerializeDataFrameHeader(large_body.length(),
+                                                 SimpleBufferAllocator::Get());
+  std::string data2 = UsesHttp3()
+                          ? absl::StrCat(header.AsStringView(), large_body)
+                          : large_body;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
   EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -409,9 +408,8 @@
   response_headers_[":status"] = "200 OK";
   response_headers_["content-length"] = "5";
   std::string body = "Yummm";
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body.length(), SimpleBufferAllocator::Get());
 
   memory_cache_backend_.AddResponse("www.google.com", "/bar",
                                     std::move(response_headers_), body);
@@ -421,7 +419,7 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+    EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
   }
   EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
 
@@ -442,9 +440,8 @@
   response_headers_["content-length"] = "5";
   std::string body = "Yummm";
 
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body.length(), SimpleBufferAllocator::Get());
 
   memory_cache_backend_.AddResponse("www.google.com", "/bar",
                                     std::move(response_headers_), body);
@@ -454,7 +451,7 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+    EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
   }
   EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
 
@@ -507,9 +504,8 @@
   response_headers_["content-length"] = "5";
   std::string body = "Yummm";
 
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body.length(), SimpleBufferAllocator::Get());
 
   memory_cache_backend_.AddResponse("www.google.com", "/bar",
                                     std::move(response_headers_), body);
@@ -518,7 +514,7 @@
   InSequence s;
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+    EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
   }
   EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
 
@@ -538,9 +534,8 @@
   (*request_headers)[":authority"] = host;
   (*request_headers)[":method"] = "GET";
 
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body.length(), SimpleBufferAllocator::Get());
   std::vector<spdy::Http2HeaderBlock> early_hints;
   // Add two Early Hints.
   const size_t kNumEarlyHintsResponses = 2;
@@ -562,7 +557,7 @@
   }
   EXPECT_CALL(*stream_, WriteHeadersMock(false));
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+    EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
   }
   EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
 
@@ -608,9 +603,8 @@
   response_headers_[":status"] = "200";
   response_headers_["content-length"] = "5";
   const std::string kBody = "Hello";
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(kBody.length(), &buffer);
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
   memory_cache_backend_.AddResponse(kHost, kPath, std::move(response_headers_),
                                     kBody);
 
@@ -620,7 +614,7 @@
   EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
 
   if (UsesHttp3()) {
-    EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _,
+    EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header.size(), _,
                                      NO_FIN, _, _));
   }
   EXPECT_CALL(session_,
@@ -767,11 +761,10 @@
   header_list.OnHeaderBlockEnd(128, 128);
   EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
   stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data = UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data =
+      UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
@@ -793,11 +786,10 @@
   header_list.OnHeaderBlockEnd(128, 128);
   EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
   stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
-  std::unique_ptr<char[]> buffer;
-  QuicByteCount header_length =
-      HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
-  std::string header = std::string(buffer.get(), header_length);
-  std::string data = UsesHttp3() ? header + body_ : body_;
+  QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+      body_.length(), SimpleBufferAllocator::Get());
+  std::string data =
+      UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
   stream_->OnStreamFrame(
       QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
   EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));