// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef QUICHE_QUIC_CORE_QUIC_SEEKER_H_
#define QUICHE_QUIC_CORE_QUIC_SEEKER_H_

#include <algorithm>

#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h"
#include "net/third_party/quiche/src/quic/core/quic_interval.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"

namespace quic {

namespace test {
class QuicIntervalDequePeer;
}  // namespace test

// QuicIntervalDeque<T, C> is a templated wrapper container, wrapping random
// access data structures. The wrapper allows items to be added to the
// underlying container with intervals associated with each item. The intervals
// _should_ be added already sorted and represent searchable indices. The search
// is optimized for sequential usage.
//
// As the intervals are to be searched sequentially the search for the next
// interval can be achieved in O(1), by simply remembering the last interval
// consumed. The structure also checks for an "off-by-one" use case wherein the
// |cached_index_| is off by one index as the caller didn't call operator |++|
// to increment the index. Other intervals can be found in O(log(n)) as they are
// binary searchable. A use case for this structure is packet buffering: Packets
// are sent sequentially but can sometimes needed for retransmission. The
// packets and their payloads are added with associated intervals representing
// data ranges they carry. When a user asks for a particular interval it's very
// likely they are requesting the next sequential interval, receiving it in O(1)
// time. Updating the sequential index is done automatically through the
// |DataAt| method and its iterator operator |++|.
//
// The intervals are represented using the usual C++ STL convention, namely as
// the half-open QuicInterval [min, max). A point p is considered to be
// contained in the QuicInterval iff p >= min && p < max. One consequence of
// this definition is that for any non-empty QuicInterval, min is contained in
// the QuicInterval but max is not. There is no canonical representation for the
// empty QuicInterval; and empty intervals are forbidden from being added to
// this container as they would be unsearchable.
//
// The type T is required to be copy-constructable or move-constructable. The
// type T is also expected to have an |interval()| method returning a
// QuicInterval<std::size> for the particular value. The type C is required to
// be a random access container supporting the methods |pop_front|, |push_back|,
// |operator[]|, |size|, and iterator support for |std::lower_bound| eg. a
// |deque| or |vector|.
//
// The QuicIntervalDeque<T, C>, like other C++ STL random access containers,
// doesn't have any explicit support for any equality operators.
//
//
// Examples with internal state:
//
//   // An example class to be stored inside the Interval Deque.
//   struct IntervalVal {
//     const int32_t val;
//     const size_t interval_begin, interval_end;
//     QuicInterval<size_t> interval();
//   };
//   typedef IntervalVal IV;
//   QuicIntervialDeque<IntervalValue> deque;
//
//   // State:
//   //   cached_index -> None
//   //   container -> {}
//
//   // Add interval items
//   deque.PushBack(IV(val: 0, interval_begin: 0, interval_end: 10));
//   deque.PushBack(IV(val: 1, interval_begin: 20, interval_end: 25));
//   deque.PushBack(IV(val: 2, interval_begin: 25, interval_end: 30));
//
//   // State:
//   //   cached_index -> 0
//   //   container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
//
//   // Look for 0 and return [0, 10). Time: O(1)
//   auto it = deque.DataAt(0);
//   assert(it->val == 0);
//   it++;  // Increment and move the |cached_index_| over [0, 10) to [20, 25).
//   assert(it->val == 1);
//
//   // State:
//   //   cached_index -> 1
//   //   container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
//
//   // Look for 20 and return [20, 25). Time: O(1)
//   auto it = deque.DataAt(20); // |cached_index_| remains unchanged.
//   assert(it->val == 1);
//
//   // State:
//   //   cached_index -> 1
//   //   container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
//
//   // Look for 15 and return deque.DataEnd(). Time: O(log(n))
//   auto it = deque.DataAt(15); // |cached_index_| remains unchanged.
//   assert(it == deque.DataEnd());
//
//   // Look for 25 and return [25, 30). Time: O(1) with off-by-one.
//   auto it = deque.DataAt(25); // |cached_index_| is updated to 2.
//   assert(it->val == 2);
//   it++; // |cached_index_| is set to |None| as all data has been iterated.
//
//
//   // State:
//   //   cached_index -> None
//   //   container -> {{0, [0, 10)}, {1, [20, 25)}, {2, [25, 30)}}
//
//   // Look again for 0 and return [0, 10). Time: O(log(n))
//   auto it = deque.DataAt(0);
//
//
//   deque.PopFront();  // Pop -> {0, [0, 10)}
//
//   // State:
//   //   cached_index -> None
//   //   container -> {{1, [20, 25)}, {2, [25, 30)}}
//
//   deque.PopFront();  // Pop -> {1, [20, 25)}
//
//   // State:
//   //   cached_index -> None
//   //   container -> {{2, [25, 30)}}
//
//   deque.PushBack(IV(val: 3, interval_begin: 35, interval_end: 50));
//
//   // State:
//   //   cached_index -> 1
//   //   container -> {{2, [25, 30)}, {3, [35, 50)}}

template <class T, class C = QUIC_NO_EXPORT QuicCircularDeque<T>>
class QUIC_NO_EXPORT QuicIntervalDeque {
 public:
  class QUIC_NO_EXPORT Iterator {
   public:
    // Used by |std::lower_bound|
    using iterator_category = std::forward_iterator_tag;
    using value_type = T;
    using difference_type = std::ptrdiff_t;
    using pointer = T*;
    using reference = T&;

    // Every increment of the iterator will increment the |cached_index_| if
    // |index_| is larger than the current |cached_index_|. |index_| is bounded
    // at |deque_.size()| and any attempt to increment above that will be
    // ignored. Once an iterator has iterated all elements the |cached_index_|
    // will be reset.
    Iterator(std::size_t index, QuicIntervalDeque* deque)
        : index_(index), deque_(deque) {}
    // Only the ++ operator attempts to update the cached index. Other operators
    // are used by |lower_bound| to binary search and are thus private.
    Iterator& operator++() {
      // Don't increment when we are at the end.
      const std::size_t container_size = deque_->container_.size();
      if (index_ >= container_size) {
        QUIC_BUG << "Iterator out of bounds.";
        return *this;
      }
      index_++;
      if (deque_->cached_index_.has_value()) {
        const std::size_t cached_index = deque_->cached_index_.value();
        // If all items are iterated then reset the |cached_index_|
        if (index_ == container_size) {
          deque_->cached_index_.reset();
        } else {
          // Otherwise the new |cached_index_| is the max of itself and |index_|
          if (cached_index < index_) {
            deque_->cached_index_ = index_;
          }
        }
      }
      return *this;
    }
    Iterator operator++(int) {
      Iterator copy = *this;
      ++(*this);
      return copy;
    }
    reference operator*() { return deque_->container_[index_]; }
    pointer operator->() { return &deque_->container_[index_]; }
    bool operator==(const Iterator& rhs) const {
      return index_ == rhs.index_ && deque_ == rhs.deque_;
    }
    bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }

   private:
    // A set of private operators for |std::lower_bound|
    Iterator operator+(difference_type amount) const {
      Iterator copy = *this;
      copy.index_ += amount;
      DCHECK(copy.index_ < copy.deque_->size());
      return copy;
    }
    Iterator& operator+=(difference_type amount) {
      index_ += amount;
      DCHECK(index_ < deque_->size());
      return *this;
    }
    difference_type operator-(const Iterator& rhs) const {
      return static_cast<difference_type>(index_) -
             static_cast<difference_type>(rhs.index_);
    }

    // |index_| is the index of the item in |*deque_|.
    std::size_t index_;
    // |deque_| is a pointer to the container the iterator came from.
    QuicIntervalDeque* deque_;

    friend class QuicIntervalDeque;
  };

  QuicIntervalDeque();

  // Adds an item to the underlying container. The |item|'s interval _should_ be
  // strictly greater than the last interval added.
  void PushBack(T&& item);
  void PushBack(const T& item);
  // Removes the front/top of the underlying container and the associated
  // interval.
  void PopFront();
  // Returns an iterator to the beginning of the data. The iterator will move
  // the |cached_index_| as the iterator moves.
  Iterator DataBegin();
  // Returns an iterator to the end of the data.
  Iterator DataEnd();
  // Returns an iterator pointing to the item in |interval_begin|. The iterator
  // will move the |cached_index_| as the iterator moves.
  Iterator DataAt(const std::size_t interval_begin);

  // Returns the number of items contained inside the structure.
  std::size_t Size() const;
  // Returns whether the structure is empty.
  bool Empty() const;

 private:
  struct QUIC_NO_EXPORT IntervalCompare {
    bool operator()(const T& item, std::size_t interval_begin) const {
      return item.interval().max() <= interval_begin;
    }
  };

  template <class U>
  void PushBackUniversal(U&& item);

  Iterator Search(const std::size_t interval_begin,
                  const std::size_t begin_index,
                  const std::size_t end_index);

  // For accessing the |cached_index_|
  friend class test::QuicIntervalDequePeer;

  C container_;
  quiche::QuicheOptional<std::size_t> cached_index_;
};

template <class T, class C>
QuicIntervalDeque<T, C>::QuicIntervalDeque() {}

template <class T, class C>
void QuicIntervalDeque<T, C>::PushBack(T&& item) {
  PushBackUniversal(std::move(item));
}

template <class T, class C>
void QuicIntervalDeque<T, C>::PushBack(const T& item) {
  PushBackUniversal(item);
}

template <class T, class C>
void QuicIntervalDeque<T, C>::PopFront() {
  if (container_.size() == 0) {
    QUIC_BUG << "Trying to pop from an empty container.";
    return;
  }
  container_.pop_front();
  if (container_.size() == 0) {
    cached_index_.reset();
  }
  if (cached_index_.value_or(0) > 0) {
    cached_index_ = cached_index_.value() - 1;
  }
}

template <class T, class C>
typename QuicIntervalDeque<T, C>::Iterator
QuicIntervalDeque<T, C>::DataBegin() {
  return Iterator(0, this);
}

template <class T, class C>
typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::DataEnd() {
  return Iterator(container_.size(), this);
}

template <class T, class C>
typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::DataAt(
    const std::size_t interval_begin) {
  // No |cached_index_| value means all items can be searched.
  if (!cached_index_.has_value()) {
    return Search(interval_begin, 0, container_.size());
  }

  const std::size_t cached_index = cached_index_.value();
  DCHECK(cached_index < container_.size());

  const QuicInterval<size_t> cached_interval =
      container_[cached_index].interval();
  // Does our cached index point directly to what we want?
  if (cached_interval.Contains(interval_begin)) {
    return Iterator(cached_index, this);
  }

  // Are we off-by-one?
  const std::size_t next_index = cached_index + 1;
  if (next_index < container_.size()) {
    if (container_[next_index].interval().Contains(interval_begin)) {
      cached_index_ = next_index;
      return Iterator(next_index, this);
    }
  }

  // Small optimization:
  // Determine if we should binary search above or below the cached interval.
  const std::size_t cached_begin = cached_interval.min();
  bool looking_below = interval_begin < cached_begin;
  const std::size_t lower = looking_below ? 0 : cached_index + 1;
  const std::size_t upper = looking_below ? cached_index : container_.size();
  Iterator ret = Search(interval_begin, lower, upper);
  if (ret == DataEnd()) {
    return ret;
  }
  // Update the |cached_index_| to point to the higher index.
  if (!looking_below) {
    cached_index_ = ret.index_;
  }
  return ret;
}

template <class T, class C>
std::size_t QuicIntervalDeque<T, C>::Size() const {
  return container_.size();
}

template <class T, class C>
bool QuicIntervalDeque<T, C>::Empty() const {
  return container_.size() == 0;
}

template <class T, class C>
template <class U>
void QuicIntervalDeque<T, C>::PushBackUniversal(U&& item) {
  QuicInterval<std::size_t> interval = item.interval();
  // Adding an empty interval is a bug.
  if (interval.Empty()) {
    QUIC_BUG << "Trying to save empty interval to QuicCircularDeque.";
    return;
  }
  container_.push_back(std::forward<U>(item));
  if (!cached_index_.has_value()) {
    cached_index_ = container_.size() - 1;
  }
}

template <class T, class C>
typename QuicIntervalDeque<T, C>::Iterator QuicIntervalDeque<T, C>::Search(
    const std::size_t interval_begin,
    const std::size_t begin_index,
    const std::size_t end_index) {
  auto begin = container_.begin() + begin_index;
  auto end = container_.begin() + end_index;
  auto res = std::lower_bound(begin, end, interval_begin, IntervalCompare());
  // Just because we run |lower_bound| and it didn't return |container_.end()|
  // doesn't mean we found our desired interval.
  if (res != end && res->interval().Contains(interval_begin)) {
    return Iterator(std::distance(begin, res) + begin_index, this);
  }
  return DataEnd();
}

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_SEEKER_H_
