Internal QUICHE change

PiperOrigin-RevId: 278613873
Change-Id: I7362668613bfb081adefa1fcb185c0b0f3df74ac
diff --git a/quic/core/frames/quic_ack_frame.cc b/quic/core/frames/quic_ack_frame.cc
index 389f1c0..72e806c 100644
--- a/quic/core/frames/quic_ack_frame.cc
+++ b/quic/core/frames/quic_ack_frame.cc
@@ -15,13 +15,6 @@
 
 const QuicPacketCount kMaxPrintRange = 128;
 
-uint64_t PacketNumberIntervalLength(
-    const QuicInterval<QuicPacketNumber>& interval) {
-  if (interval.Empty()) {
-    return 0u;
-  }
-  return interval.max() - interval.min();
-}
 }  // namespace
 
 bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
@@ -86,77 +79,8 @@
   if (!packet_number.IsInitialized()) {
     return;
   }
-  // Check if the deque is empty
-  if (packet_number_deque_.empty()) {
-    packet_number_deque_.push_front(
-        QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
-    return;
-  }
-  QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
-
-  // Check for the typical case,
-  // when the next packet in order is acked
-  if (back.max() == packet_number) {
-    packet_number_deque_.back().SetMax(packet_number + 1);
-    return;
-  }
-  // Check if the next packet in order is skipped
-  if (back.max() < packet_number) {
-    packet_number_deque_.push_back(
-        QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
-    return;
-  }
-
-  QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
-  // Check if the packet can be  popped on the front
-  if (front.min() > packet_number + 1) {
-    packet_number_deque_.push_front(
-        QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
-    return;
-  }
-  if (front.min() == packet_number + 1) {
-    packet_number_deque_.front().SetMin(packet_number);
-    return;
-  }
-
-  int i = packet_number_deque_.size() - 1;
-  // Iterating through the queue backwards
-  // to find a proper place for the packet
-  while (i >= 0) {
-    QuicInterval<QuicPacketNumber> packet_interval = packet_number_deque_[i];
-    DCHECK(packet_interval.min() < packet_interval.max());
-    // Check if the packet is contained in an interval already
-    if (packet_interval.Contains(packet_number)) {
-      return;
-    }
-
-    // Check if the packet can extend an interval.
-    if (packet_interval.max() == packet_number) {
-      packet_number_deque_[i].SetMax(packet_number + 1);
-      return;
-    }
-    // Check if the packet can extend an interval
-    // and merge two intervals if needed.
-    // There is no need to merge an interval in the previous
-    // if statement, as all merges will happen here.
-    if (packet_interval.min() == packet_number + 1) {
-      packet_number_deque_[i].SetMin(packet_number);
-      if (i > 0 && packet_number == packet_number_deque_[i - 1].max()) {
-        packet_number_deque_[i - 1].SetMax(packet_interval.max());
-        packet_number_deque_.erase(packet_number_deque_.begin() + i);
-      }
-      return;
-    }
-
-    // Check if we need to make a new interval for the packet
-    if (packet_interval.max() < packet_number + 1) {
-      packet_number_deque_.insert(
-          packet_number_deque_.begin() + i + 1,
-          QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
-      return;
-    }
-    i--;
-  }
+  packet_number_intervals_.AddOptimizedForAppend(packet_number,
+                                                 packet_number + 1);
 }
 
 void PacketNumberQueue::AddRange(QuicPacketNumber lower,
@@ -164,136 +88,93 @@
   if (!lower.IsInitialized() || !higher.IsInitialized() || lower >= higher) {
     return;
   }
-  if (packet_number_deque_.empty()) {
-    packet_number_deque_.push_front(
-        QuicInterval<QuicPacketNumber>(lower, higher));
-    return;
-  }
-  QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
 
-  if (back.max() == lower) {
-    // Check for the typical case,
-    // when the next packet in order is acked
-    packet_number_deque_.back().SetMax(higher);
-    return;
-  }
-  if (back.max() < lower) {
-    // Check if the next packet in order is skipped
-    packet_number_deque_.push_back(
-        QuicInterval<QuicPacketNumber>(lower, higher));
-    return;
-  }
-  QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
-  // Check if the packets are being added in reverse order
-  if (front.min() == higher) {
-    packet_number_deque_.front().SetMin(lower);
-  } else if (front.min() > higher) {
-    packet_number_deque_.push_front(
-        QuicInterval<QuicPacketNumber>(lower, higher));
+  const auto new_interval = QuicInterval<QuicPacketNumber>(lower, higher);
 
-  } else {
+  if (!packet_number_intervals_.Empty() &&
+      packet_number_intervals_.SpanningInterval().Intersects(new_interval)) {
+    // TODO(wub): Remove this QUIC_BUG, or the AddRange method entirely.
     // Ranges must be above or below all existing ranges.
     QUIC_BUG << "AddRange only supports adding packets above or below the "
              << "current min:" << Min() << " and max:" << Max()
              << ", but adding [" << lower << "," << higher << ")";
+    return;
   }
+
+  packet_number_intervals_.AddOptimizedForAppend(new_interval);
 }
 
 bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
   if (!higher.IsInitialized() || Empty()) {
     return false;
   }
-  const QuicPacketNumber old_min = Min();
-  while (!packet_number_deque_.empty()) {
-    QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
-    if (front.max() < higher) {
-      packet_number_deque_.pop_front();
-    } else if (front.min() < higher && front.max() >= higher) {
-      packet_number_deque_.front().SetMin(higher);
-      if (front.max() == higher) {
-        packet_number_deque_.pop_front();
-      }
-      break;
-    } else {
-      break;
-    }
-  }
-
-  return Empty() || old_min != Min();
+  return packet_number_intervals_.TrimLessThan(higher);
 }
 
 void PacketNumberQueue::RemoveSmallestInterval() {
-  QUIC_BUG_IF(packet_number_deque_.size() < 2)
+  // TODO(wub): Move this QUIC_BUG to upper level.
+  QUIC_BUG_IF(packet_number_intervals_.Size() < 2)
       << (Empty() ? "No intervals to remove."
                   : "Can't remove the last interval.");
-  packet_number_deque_.pop_front();
+  packet_number_intervals_.PopFront();
 }
 
 void PacketNumberQueue::Clear() {
-  packet_number_deque_.clear();
+  packet_number_intervals_.Clear();
 }
 
 bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
-  if (!packet_number.IsInitialized() || packet_number_deque_.empty()) {
+  if (!packet_number.IsInitialized()) {
     return false;
   }
-  if (packet_number_deque_.front().min() > packet_number ||
-      packet_number_deque_.back().max() <= packet_number) {
-    return false;
-  }
-  for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
-    if (interval.Contains(packet_number)) {
-      return true;
-    }
-  }
-  return false;
+  return packet_number_intervals_.Contains(packet_number);
 }
 
 bool PacketNumberQueue::Empty() const {
-  return packet_number_deque_.empty();
+  return packet_number_intervals_.Empty();
 }
 
 QuicPacketNumber PacketNumberQueue::Min() const {
   DCHECK(!Empty());
-  return packet_number_deque_.front().min();
+  return packet_number_intervals_.begin()->min();
 }
 
 QuicPacketNumber PacketNumberQueue::Max() const {
   DCHECK(!Empty());
-  return packet_number_deque_.back().max() - 1;
+  return packet_number_intervals_.rbegin()->max() - 1;
 }
 
 QuicPacketCount PacketNumberQueue::NumPacketsSlow() const {
   QuicPacketCount n_packets = 0;
-  for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
-    n_packets += PacketNumberIntervalLength(interval);
+  for (const auto& interval : packet_number_intervals_) {
+    n_packets += interval.Length();
   }
   return n_packets;
 }
 
 size_t PacketNumberQueue::NumIntervals() const {
-  return packet_number_deque_.size();
+  return packet_number_intervals_.Size();
 }
 
 PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
-  return packet_number_deque_.begin();
+  return packet_number_intervals_.begin();
 }
 
 PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
-  return packet_number_deque_.end();
+  return packet_number_intervals_.end();
 }
 
 PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
-  return packet_number_deque_.rbegin();
+  return packet_number_intervals_.rbegin();
 }
 
 PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
-  return packet_number_deque_.rend();
+  return packet_number_intervals_.rend();
 }
 
 QuicPacketCount PacketNumberQueue::LastIntervalLength() const {
   DCHECK(!Empty());
-  return PacketNumberIntervalLength(packet_number_deque_.back());
+  return packet_number_intervals_.rbegin()->Length();
 }
 
 // Largest min...max range for packet numbers where we print the numbers
diff --git a/quic/core/frames/quic_ack_frame.h b/quic/core/frames/quic_ack_frame.h
index 771d93e..18675a8 100644
--- a/quic/core/frames/quic_ack_frame.h
+++ b/quic/core/frames/quic_ack_frame.h
@@ -8,6 +8,7 @@
 #include <ostream>
 
 #include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval_set.h"
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -28,9 +29,8 @@
   PacketNumberQueue& operator=(const PacketNumberQueue& other);
   PacketNumberQueue& operator=(PacketNumberQueue&& other);
 
-  typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_iterator
-      const_iterator;
-  typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_reverse_iterator
+  typedef QuicIntervalSet<QuicPacketNumber>::const_iterator const_iterator;
+  typedef QuicIntervalSet<QuicPacketNumber>::const_reverse_iterator
       const_reverse_iterator;
 
   // Adds |packet_number| to the set of packets in the queue.
@@ -38,6 +38,7 @@
 
   // Adds packets between [lower, higher) to the set of packets in the queue. It
   // is undefined behavior to call this with |higher| < |lower|.
+  // NOTE(wub): Only used in tests as of Nov 2019.
   void AddRange(QuicPacketNumber lower, QuicPacketNumber higher);
 
   // Removes packets with values less than |higher| from the set of packets in
@@ -86,7 +87,7 @@
       const PacketNumberQueue& q);
 
  private:
-  QuicDeque<QuicInterval<QuicPacketNumber>> packet_number_deque_;
+  QuicIntervalSet<QuicPacketNumber> packet_number_intervals_;
 };
 
 struct QUIC_EXPORT_PRIVATE QuicAckFrame {
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 761645e..353d4e6 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -148,6 +148,7 @@
   return (Delta(target, a) < Delta(target, b)) ? a : b;
 }
 
+// TODO(wub): Remove this function & replace the callsites to interval.Length().
 uint64_t PacketNumberIntervalLength(
     const QuicInterval<QuicPacketNumber>& interval) {
   if (interval.Empty()) {
diff --git a/quic/core/quic_interval_set.h b/quic/core/quic_interval_set.h
index 0465a01..28153c1 100644
--- a/quic/core/quic_interval_set.h
+++ b/quic/core/quic_interval_set.h
@@ -73,6 +73,7 @@
   struct QUIC_NO_EXPORT IntervalLess {
     bool operator()(const value_type& a, const value_type& b) const;
   };
+  // TODO(wub): Switch to absl::btree_set when it is available in Chromium.
   typedef std::set<value_type, IntervalLess> Set;
 
  public:
@@ -152,6 +153,49 @@
   // TODO(wub): Similar to AddOptimizedForAppend, we can also have a
   // AddOptimizedForPrepend if there is a use case.
 
+  // Remove the first interval.
+  // REQUIRES: !Empty()
+  void PopFront() {
+    DCHECK(!Empty());
+    intervals_.erase(intervals_.begin());
+  }
+
+  // Trim all values that is smaller than |value|. Which means
+  // a) If all values in an interval is smaller than |value|, the entire
+  //    interval is removed.
+  // b) If some but not all values in an interval is smaller than |value|, the
+  //    min of that interval is raised to |value|.
+  // Returns true if some intervals are trimmed.
+  bool TrimLessThan(const T& value) {
+    // Number of intervals that are fully or partially trimmed.
+    size_t num_intervals_trimmed = 0;
+
+    while (!intervals_.empty()) {
+      const_iterator first_interval = intervals_.begin();
+      if (first_interval->min() >= value) {
+        break;
+      }
+
+      ++num_intervals_trimmed;
+
+      if (first_interval->max() <= value) {
+        // a) Trim the entire interval.
+        intervals_.erase(first_interval);
+        continue;
+      }
+
+      // b) Trim a prefix of the interval.
+      //
+      // Set does not allow in-place updates due to the potential of violating
+      // its ordering requirements. But increasing the min of the first interval
+      // will not break the ordering, hence the const_cast.
+      const_cast<value_type*>(&(*first_interval))->SetMin(value);
+      break;
+    }
+
+    return num_intervals_trimmed != 0;
+  }
+
   // Returns true if this QuicIntervalSet is empty.
   bool Empty() const { return intervals_.empty(); }
 
diff --git a/quic/core/quic_interval_set_test.cc b/quic/core/quic_interval_set_test.cc
index 3fb483a..efa8fe7 100644
--- a/quic/core/quic_interval_set_test.cc
+++ b/quic/core/quic_interval_set_test.cc
@@ -191,6 +191,47 @@
   EXPECT_TRUE(Check(iset, 3, 100, 150, 199, 250, 251, 350));
 }
 
+TEST_F(QuicIntervalSetTest, PopFront) {
+  QuicIntervalSet<int> iset{{100, 200}, {400, 500}, {700, 800}};
+  EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+  iset.PopFront();
+  EXPECT_TRUE(Check(iset, 2, 400, 500, 700, 800));
+
+  iset.PopFront();
+  EXPECT_TRUE(Check(iset, 1, 700, 800));
+
+  iset.PopFront();
+  EXPECT_TRUE(iset.Empty());
+}
+
+TEST_F(QuicIntervalSetTest, TrimLessThan) {
+  QuicIntervalSet<int> iset{{100, 200}, {400, 500}, {700, 800}};
+  EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+  EXPECT_FALSE(iset.TrimLessThan(99));
+  EXPECT_FALSE(iset.TrimLessThan(100));
+  EXPECT_TRUE(Check(iset, 3, 100, 200, 400, 500, 700, 800));
+
+  EXPECT_TRUE(iset.TrimLessThan(101));
+  EXPECT_TRUE(Check(iset, 3, 101, 200, 400, 500, 700, 800));
+
+  EXPECT_TRUE(iset.TrimLessThan(199));
+  EXPECT_TRUE(Check(iset, 3, 199, 200, 400, 500, 700, 800));
+
+  EXPECT_TRUE(iset.TrimLessThan(450));
+  EXPECT_TRUE(Check(iset, 2, 450, 500, 700, 800));
+
+  EXPECT_TRUE(iset.TrimLessThan(500));
+  EXPECT_TRUE(Check(iset, 1, 700, 800));
+
+  EXPECT_TRUE(iset.TrimLessThan(801));
+  EXPECT_TRUE(iset.Empty());
+
+  EXPECT_FALSE(iset.TrimLessThan(900));
+  EXPECT_TRUE(iset.Empty());
+}
+
 TEST_F(QuicIntervalSetTest, QuicIntervalSetBasic) {
   // Test Add, Get, Contains and Find
   QuicIntervalSet<int> iset;