// Copyright (c) 2012 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.

// QuicBandwidth represents a bandwidth, stored in bits per second resolution.

#ifndef QUICHE_QUIC_CORE_QUIC_BANDWIDTH_H_
#define QUICHE_QUIC_CORE_QUIC_BANDWIDTH_H_

#include <cmath>
#include <cstdint>
#include <limits>
#include <optional>
#include <ostream>
#include <string>

#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/common/platform/api/quiche_export.h"
#include "quiche/common/platform/api/quiche_logging.h"

namespace quic {

// QuicBandwidth is a thin wrapper around an int64_t representing bits per
// second. Methods and operators declared in this file do not perform range
// checks on parameters unless otherwise specified.
class QUICHE_EXPORT QuicBandwidth {
 public:
  // Creates a new QuicBandwidth with an internal value of 0.
  static constexpr QuicBandwidth Zero() { return QuicBandwidth(0); }

  // Creates a new QuicBandwidth with an internal value of INT64_MAX. The
  // infinite QuicBandwidth is only useful as a sentinel value. It cannot be
  // added to any non-zero QuicBandwidth without committing UB.
  static constexpr QuicBandwidth Infinite() {
    return QuicBandwidth(std::numeric_limits<int64_t>::max());
  }

  // Create a new QuicBandwidth holding the bits per second.
  static constexpr QuicBandwidth FromBitsPerSecond(int64_t bits_per_second) {
    return QuicBandwidth(bits_per_second);
  }

  // Create a new QuicBandwidth holding the kilo bits per second.
  static constexpr QuicBandwidth FromKBitsPerSecond(int64_t k_bits_per_second) {
    return QuicBandwidth(k_bits_per_second * 1000);
  }

  // Create a new QuicBandwidth holding the bytes per second.
  static constexpr QuicBandwidth FromBytesPerSecond(int64_t bytes_per_second) {
    return QuicBandwidth(bytes_per_second * 8);
  }

  // Create a new QuicBandwidth holding the kilo bytes per second.
  static constexpr QuicBandwidth FromKBytesPerSecond(
      int64_t k_bytes_per_second) {
    return QuicBandwidth(k_bytes_per_second * 8000);
  }

  // Create a new QuicBandwidth based on the bytes per the elapsed delta.
  static QuicBandwidth FromBytesAndTimeDelta(QuicByteCount bytes,
                                             QuicTime::Delta delta) {
    if (bytes == 0) {
      return QuicBandwidth(0);
    }

    // 1 bit is 1000000 micro bits.
    int64_t num_micro_bits = 8 * bytes * kNumMicrosPerSecond;
    if (num_micro_bits < delta.ToMicroseconds()) {
      return QuicBandwidth(1);
    }

    return QuicBandwidth(num_micro_bits / delta.ToMicroseconds());
  }

  int64_t ToBitsPerSecond() const { return bits_per_second_; }

  int64_t ToKBitsPerSecond() const { return bits_per_second_ / 1000; }

  int64_t ToBytesPerSecond() const { return bits_per_second_ / 8; }

  int64_t ToKBytesPerSecond() const { return bits_per_second_ / 8000; }

  // Returns the product of `this` and the given `time_period` when the
  // parameters are nonnegative and the computation would not overflow.
  // Otherwise, returns `std::nullopt`.
  constexpr std::optional<QuicByteCount> ToBytesPerPeriodSafe(
      QuicTime::Delta time_period) const {
    const std::optional<int64_t> bits_per_second_times_microseconds =
        SafeMultiplyNonNegatives(bits_per_second_,
                                 time_period.ToMicroseconds());
    if (!bits_per_second_times_microseconds.has_value()) {
      return std::nullopt;
    }
    return *bits_per_second_times_microseconds / 8 / kNumMicrosPerSecond;
  }

  constexpr QuicByteCount ToBytesPerPeriod(QuicTime::Delta time_period) const {
    // TODO: b/461578611 - Remove the short-circuit on negative `time_period`
    // once we're certain incoming deltas are non-negative.
    QUICHE_DCHECK(time_period < QuicTime::Delta::Zero() ||
                  ToBytesPerPeriodSafe(time_period).has_value())
        << "bits_per_second: " << bits_per_second_
        << ", time_period: " << time_period.ToMicroseconds() << " us";
    return bits_per_second_ * time_period.ToMicroseconds() / 8 /
           kNumMicrosPerSecond;
  }

  int64_t ToKBytesPerPeriod(QuicTime::Delta time_period) const {
    return bits_per_second_ * time_period.ToMicroseconds() / 8000 /
           kNumMicrosPerSecond;
  }

  bool IsZero() const { return bits_per_second_ == 0; }
  bool IsInfinite() const {
    return bits_per_second_ == Infinite().ToBitsPerSecond();
  }

  constexpr QuicTime::Delta TransferTime(QuicByteCount bytes) const {
    if (bits_per_second_ == 0) {
      return QuicTime::Delta::Zero();
    }
    return QuicTime::Delta::FromMicroseconds(bytes * 8 * kNumMicrosPerSecond /
                                             bits_per_second_);
  }

  std::string ToDebuggingValue() const;

  template <typename Sink>
  friend void AbslStringify(Sink& sink, QuicBandwidth bandwidth) {
    sink.Append(bandwidth.ToDebuggingValue());
  }

 private:
  // Returns the value of `a * b` if both `a` and `b` are non-negative and the
  // result fits in `int64_t`. Otherwise, returns `std::nullopt`.
  static constexpr std::optional<int64_t> SafeMultiplyNonNegatives(int64_t a,
                                                                   int64_t b) {
    if (a < 0 || b < 0) {
      return std::nullopt;
    }
    if (a == 0 || b == 0) {
      return 0;
    }
    if (a > std::numeric_limits<int64_t>::max() / b) {
      return std::nullopt;
    }
    return a * b;
  }

  explicit constexpr QuicBandwidth(int64_t bits_per_second)
      : bits_per_second_(bits_per_second >= 0 ? bits_per_second : 0) {}

  int64_t bits_per_second_;

  friend constexpr QuicBandwidth operator+(QuicBandwidth lhs,
                                           QuicBandwidth rhs);
  friend constexpr QuicBandwidth operator-(QuicBandwidth lhs,
                                           QuicBandwidth rhs);
  friend QuicBandwidth operator*(QuicBandwidth lhs, float rhs);
};

// Non-member relational operators for QuicBandwidth.
inline bool operator==(QuicBandwidth lhs, QuicBandwidth rhs) {
  return lhs.ToBitsPerSecond() == rhs.ToBitsPerSecond();
}
inline bool operator!=(QuicBandwidth lhs, QuicBandwidth rhs) {
  return !(lhs == rhs);
}
inline bool operator<(QuicBandwidth lhs, QuicBandwidth rhs) {
  return lhs.ToBitsPerSecond() < rhs.ToBitsPerSecond();
}
inline bool operator>(QuicBandwidth lhs, QuicBandwidth rhs) {
  return rhs < lhs;
}
inline bool operator<=(QuicBandwidth lhs, QuicBandwidth rhs) {
  return !(rhs < lhs);
}
inline bool operator>=(QuicBandwidth lhs, QuicBandwidth rhs) {
  return !(lhs < rhs);
}

// Non-member arithmetic operators for QuicBandwidth.
inline constexpr QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs) {
  return QuicBandwidth(lhs.bits_per_second_ + rhs.bits_per_second_);
}
inline constexpr QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs) {
  return QuicBandwidth(lhs.bits_per_second_ - rhs.bits_per_second_);
}
inline QuicBandwidth operator*(QuicBandwidth lhs, float rhs) {
  return QuicBandwidth(
      static_cast<int64_t>(std::llround(lhs.bits_per_second_ * rhs)));
}
inline QuicBandwidth operator*(float lhs, QuicBandwidth rhs) {
  return rhs * lhs;
}
inline constexpr QuicByteCount operator*(QuicBandwidth lhs,
                                         QuicTime::Delta rhs) {
  return lhs.ToBytesPerPeriod(rhs);
}
inline constexpr QuicByteCount operator*(QuicTime::Delta lhs,
                                         QuicBandwidth rhs) {
  return rhs * lhs;
}

// Override stream output operator for gtest.
inline std::ostream& operator<<(std::ostream& output,
                                const QuicBandwidth bandwidth) {
  output << bandwidth.ToDebuggingValue();
  return output;
}

}  // namespace quic
#endif  // QUICHE_QUIC_CORE_QUIC_BANDWIDTH_H_
