Introduce QuicStreamSequencer::IsAllDataAvailable()

This is useful in situations where the stream consumer reads data from the stream in chunks, and will not actually mark an incomplete chunk as consumed.

PiperOrigin-RevId: 452598666
diff --git a/quiche/quic/core/http/web_transport_http3.cc b/quiche/quic/core/http/web_transport_http3.cc
index 6c9cbff..a9babe8 100644
--- a/quiche/quic/core/http/web_transport_http3.cc
+++ b/quiche/quic/core/http/web_transport_http3.cc
@@ -347,8 +347,7 @@
     // If all of the data has been received, and we still cannot associate the
     // stream with a session, consume all of the data so that the stream can
     // be closed.
-    if (sequencer()->NumBytesConsumed() + sequencer()->NumBytesBuffered() >=
-        sequencer()->close_offset()) {
+    if (sequencer()->IsAllDataAvailable()) {
       QUIC_DLOG(WARNING)
           << ENDPOINT << "Failed to associate WebTransport stream " << id()
           << " with a session because the stream ended prematurely.";
diff --git a/quiche/quic/core/quic_stream_sequencer.cc b/quiche/quic/core/quic_stream_sequencer.cc
index 03fd990..fa76841 100644
--- a/quiche/quic/core/quic_stream_sequencer.cc
+++ b/quiche/quic/core/quic_stream_sequencer.cc
@@ -292,6 +292,11 @@
   return buffered_frames_.BytesConsumed();
 }
 
+bool QuicStreamSequencer::IsAllDataAvailable() const {
+  QUICHE_DCHECK_LE(NumBytesConsumed() + NumBytesBuffered(), close_offset_);
+  return NumBytesConsumed() + NumBytesBuffered() >= close_offset_;
+}
+
 const std::string QuicStreamSequencer::DebugString() const {
   // clang-format off
   return absl::StrCat("QuicStreamSequencer:",
diff --git a/quiche/quic/core/quic_stream_sequencer.h b/quiche/quic/core/quic_stream_sequencer.h
index e201cc1..9953c75 100644
--- a/quiche/quic/core/quic_stream_sequencer.h
+++ b/quiche/quic/core/quic_stream_sequencer.h
@@ -139,6 +139,10 @@
   // Number of bytes has been consumed.
   QuicStreamOffset NumBytesConsumed() const;
 
+  // Returns true if all of the data within the stream up until the FIN is
+  // available.
+  bool IsAllDataAvailable() const;
+
   QuicStreamOffset close_offset() const { return close_offset_; }
 
   int num_frames_received() const { return num_frames_received_; }
diff --git a/quiche/quic/core/quic_stream_sequencer_test.cc b/quiche/quic/core/quic_stream_sequencer_test.cc
index bfac366..3ac6d88 100644
--- a/quiche/quic/core/quic_stream_sequencer_test.cc
+++ b/quiche/quic/core/quic_stream_sequencer_test.cc
@@ -223,8 +223,10 @@
     ConsumeData(3);
   }));
   EXPECT_FALSE(sequencer_->IsClosed());
+  EXPECT_FALSE(sequencer_->IsAllDataAvailable());
   OnFinFrame(3, "def");
   EXPECT_TRUE(sequencer_->IsClosed());
+  EXPECT_TRUE(sequencer_->IsAllDataAvailable());
 }
 
 TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
@@ -239,6 +241,7 @@
     ConsumeData(3);
   }));
   EXPECT_FALSE(sequencer_->IsClosed());
+  EXPECT_TRUE(sequencer_->IsAllDataAvailable());
   sequencer_->SetUnblocked();
   EXPECT_TRUE(sequencer_->IsClosed());
   EXPECT_EQ(0u, NumBufferedBytes());
@@ -260,6 +263,7 @@
   OnFinFrame(0, "");
   EXPECT_EQ(0u, NumBufferedBytes());
   EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
+  EXPECT_TRUE(sequencer_->IsAllDataAvailable());
 }
 
 TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) {