// Copyright (c) 2022 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_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_
#define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_

#include <cstdint>
#include <memory>
#include <optional>

#include "absl/container/flat_hash_map.h"
#include "quiche/quic/load_balancer/load_balancer_server_id.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"

namespace quic {

// This class wraps an absl::flat_hash_map which associates server IDs to an
// arbitrary type T. It validates that all server ids are of the same fixed
// length. This might be used by a load balancer to connect a server ID with a
// pool member data structure.
template <typename T>
class QUIC_EXPORT_PRIVATE LoadBalancerServerIdMap {
 public:
  // Returns a newly created pool for server IDs of length |server_id_len|, or
  // nullptr if |server_id_len| is invalid.
  static std::shared_ptr<LoadBalancerServerIdMap> Create(uint8_t server_id_len);

  // Returns the entry associated with |server_id|, if present. For small |T|,
  // use Lookup. For large |T|, use LookupNoCopy.
  std::optional<const T> Lookup(LoadBalancerServerId server_id) const;
  const T* LookupNoCopy(LoadBalancerServerId server_id) const;

  // Updates the table so that |value| is associated with |server_id|. Sets
  // QUIC_BUG if the length is incorrect for this map.
  void AddOrReplace(LoadBalancerServerId server_id, T value);

  // Removes the entry associated with |server_id|.
  void Erase(const LoadBalancerServerId server_id) {
    server_id_table_.erase(server_id);
  }

  uint8_t server_id_len() const { return server_id_len_; }

 private:
  LoadBalancerServerIdMap(uint8_t server_id_len)
      : server_id_len_(server_id_len) {}

  const uint8_t server_id_len_;  // All server IDs must be of this length.
  absl::flat_hash_map<LoadBalancerServerId, T> server_id_table_;
};

template <typename T>
std::shared_ptr<LoadBalancerServerIdMap<T>> LoadBalancerServerIdMap<T>::Create(
    const uint8_t server_id_len) {
  if (server_id_len == 0 || server_id_len > kLoadBalancerMaxServerIdLen) {
    QUIC_BUG(quic_bug_434893339_01)
        << "Tried to configure map with server ID length "
        << static_cast<int>(server_id_len);
    return nullptr;
  }
  return std::make_shared<LoadBalancerServerIdMap<T>>(
      LoadBalancerServerIdMap(server_id_len));
}

template <typename T>
std::optional<const T> LoadBalancerServerIdMap<T>::Lookup(
    const LoadBalancerServerId server_id) const {
  if (server_id.length() != server_id_len_) {
    QUIC_BUG(quic_bug_434893339_02)
        << "Lookup with a " << static_cast<int>(server_id.length())
        << " byte server ID, map requires " << static_cast<int>(server_id_len_);
    return std::optional<T>();
  }
  auto it = server_id_table_.find(server_id);
  return (it != server_id_table_.end()) ? it->second : std::optional<const T>();
}

template <typename T>
const T* LoadBalancerServerIdMap<T>::LookupNoCopy(
    const LoadBalancerServerId server_id) const {
  if (server_id.length() != server_id_len_) {
    QUIC_BUG(quic_bug_434893339_02)
        << "Lookup with a " << static_cast<int>(server_id.length())
        << " byte server ID, map requires " << static_cast<int>(server_id_len_);
    return nullptr;
  }
  auto it = server_id_table_.find(server_id);
  return (it != server_id_table_.end()) ? &it->second : nullptr;
}

template <typename T>
void LoadBalancerServerIdMap<T>::AddOrReplace(
    const LoadBalancerServerId server_id, T value) {
  if (server_id.length() == server_id_len_) {
    server_id_table_[server_id] = value;
  } else {
    QUIC_BUG(quic_bug_434893339_03)
        << "Server ID of " << static_cast<int>(server_id.length())
        << " bytes; this map requires " << static_cast<int>(server_id_len_);
  }
}

}  // namespace quic

#endif  // QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_
