// Copyright 2020 The Fuchsia 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 SRC_LIB_VMO_STORE_STORAGE_TYPES_H_
#define SRC_LIB_VMO_STORE_STORAGE_TYPES_H_

#include <lib/stdcompat/optional.h>

#include <random>

#include <fbl/alloc_checker.h>
#include <fbl/intrusive_hash_table.h>

#include "growable_slab.h"
#include "stored_vmo.h"

namespace vmo_store {

// Defines the contract of a base storage class that can be used with `VmoStore`.
// `Key` is the type of key used to address VMOs in the store.
// `Meta` is optional user metadata associated with the `StoredVmo`s kept by the store.
template <typename _Key, typename _Meta = void>
class AbstractStorage {
 public:
  using Key = _Key;
  using Meta = _Meta;
  virtual ~AbstractStorage() = default;
  // Reserves `capacity` lots on this store.
  virtual zx_status_t Reserve(size_t capacity) = 0;
  // Insert `vmo` at `key`.
  // Must return `ZX_ERR_ALREADY_EXISTS` if `key` is already in use.
  virtual zx_status_t Insert(Key key, StoredVmo<Meta>&& vmo) = 0;
  // Allocates an unused key and associates `vmo` with it, returning the new key on success.
  virtual cpp17::optional<Key> Push(StoredVmo<Meta>&& vmo) = 0;
  // Get the `StoredVmo` associated with `key`. Returns `nullptr` if `key` doesn't match a stored
  // VMO.
  virtual StoredVmo<Meta>* Get(const Key& key) = 0;
  // Erases the VMO referenced by `key`.
  // Returns the `StoredVmo` that was previously referenced by `key`, or empty if no VMO was found
  // for `key`.
  virtual cpp17::optional<StoredVmo<Meta>> Extract(Key key) = 0;
  // Returns the number of registered `StoredVmo`s in this store.
  virtual size_t count() const = 0;

  // Implement `is_full` for types that will not automatically grow so users can be notified that
  // the container needs to grow.
  virtual bool is_full() const { return false; }
};

// A storage base for VmoStore that uses a GrowableSlab backing.
// SlabStorage is always constructed with a 0 capacity and must be manually grown by calling
// `Reserve`.
// SlabStorage is optimally suited for narrow and tight (non-sparse) key sets. It guarantees O(1)
// worst-case time-complexity on `Push`, `Get`, `Erase`, and `Insert`, but O(n) on `Reserve`.
template <typename _Key, typename _Meta = void>
class SlabStorage : public AbstractStorage<_Key, _Meta> {
 public:
  using typename AbstractStorage<_Key, _Meta>::Key;
  using typename AbstractStorage<_Key, _Meta>::Meta;
  using Item = StoredVmo<Meta>;
  SlabStorage() = default;

  inline zx_status_t Reserve(size_t capacity) override {
    slab_.GrowTo(static_cast<Key>(capacity));
    return ZX_OK;
  }

  inline zx_status_t Insert(Key key, Item&& vmo) override {
    return slab_.Insert(key, std::move(vmo));
  }

  inline cpp17::optional<Key> Push(Item&& vmo) override { return slab_.Push(std::move(vmo)); }

  inline Item* Get(const Key& key) override { return slab_.Get(key); }

  cpp17::optional<Item> Extract(Key key) override { return slab_.Erase(key); }

  inline size_t count() const override { return slab_.count(); }

  inline bool is_full() const override { return slab_.free() == 0; }

 private:
  GrowableSlab<Item, Key> slab_;
};

// A storage base for VmoStore that uses an fbl::HashTable backing.
// The hash table nodes are std::unique_ptrs that are fallibly allocated on insertion.
//
// Users should consider `HashTableStorage` over `SlabStorage` if any of the following are true:
// - The `Insert` API is expected to be used more than the `Push` API. `SlabStorage` is better
// suited than `HashTableStorage` to issue keys, but if the keys are always informed (i.e. the
// `RegisterWithKey` API on `VmoStore` is used), then `HashTableStorage` might be a better option.
// - There are no guarantees over the key space or the keys are not expected to be tightly packed.
// `SlabStorage`'s keys are simply an index in an internal vector. If there are no guarantees over
// the size or sparseness of the key set that you expect to use, `HashTableStorage` might be a
// better option.
// - Upfront memory allocation and memory reuse are not necessary.
// - The application can pay the cost of a multiplication and a mod on `Get` and absorb the O(n)
// worst-case scenario that comes with hash tables, as opposed to the stronger O(1) guarantees of
// `SlabStorage`.
//
// NOTE: This class only supports integer types as keys for simplicity. It can be expanded
// with more complex type traits derived from fbl::HashTable, but there's no immediate need for it.
template <typename _Key, typename _Meta = void>
class HashTableStorage : public AbstractStorage<_Key, _Meta> {
 public:
  using typename AbstractStorage<_Key, _Meta>::Key;
  using typename AbstractStorage<_Key, _Meta>::Meta;
  using Item = StoredVmo<Meta>;

  static_assert(std::numeric_limits<Key>::is_integer);
  static_assert(!std::numeric_limits<Key>::is_signed);

  explicit HashTableStorage(uint32_t random_seed = std::default_random_engine::default_seed)
      : rnd_distro_(0, std::numeric_limits<Key>::max()), rnd_(random_seed) {}

  HashTableStorage(HashTableStorage&& other)
      : rnd_distro_(std::move(other.rnd_distro_)),
        rnd_(std::move(other.rnd_)),
        table_(std::move(other.table_)) {}

  class HashTableVmo : public fbl::SinglyLinkedListable<std::unique_ptr<HashTableVmo>> {
   public:
    explicit HashTableVmo(Key key, Item&& vmo) : key_(key), vmo_(std::move(vmo)) {}

    // Our simple hash function just multiplies by a big prime, the DefaultHashTraits in the hash
    // table will mod by the number of buckets.
    static size_t GetHash(Key key) { return static_cast<size_t>(key) * 0xcf2fd713; }

    // Needed to comply with `DefaultKeyedObjectTraits`.
    Key GetKey() const { return key_; }

   protected:
    friend HashTableStorage;
    Key key_;
    Item vmo_;
  };

  zx_status_t Reserve(size_t capacity) override { return ZX_OK; }

  zx_status_t Insert(Key key, Item&& vmo) override {
    if (table_.find(key) != table_.end()) {
      return ZX_ERR_ALREADY_EXISTS;
    }
    fbl::AllocChecker ac;
    std::unique_ptr<HashTableVmo> holder(new (&ac) HashTableVmo(key, std::move(vmo)));
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    table_.insert(std::move(holder));
    return ZX_OK;
  }

  cpp17::optional<Key> Push(Item&& vmo) override {
    Key key = rnd_distro_(rnd_);
    auto search = table_.find(key);
    while (search != table_.end()) {
      key = rnd_distro_(rnd_);
      search = table_.find(key);
    }
    if (Insert(key, std::move(vmo)) != ZX_OK) {
      return cpp17::nullopt;
    }
    return key;
  }

  Item* Get(const Key& key) override {
    auto search = table_.find(key);
    if (search == table_.end()) {
      return nullptr;
    }
    return &search->vmo_;
  }

  inline cpp17::optional<Item> Extract(Key key) override {
    std::unique_ptr<HashTableVmo> stored_vmo = table_.erase(key);
    if (!stored_vmo) {
      return cpp17::optional<Item>();
    }

    return std::move(stored_vmo->vmo_);
  }

  inline size_t count() const override { return table_.size(); }

  inline bool is_full() const override { return false; }

 private:
  // Note: std::uniform_int_distribution does not support byte-sized types.
  template <typename T>
  struct DistroType {
    using Type = T;
  };
  template <>
  struct DistroType<bool> {
    using Type = uint16_t;
  };
  template <>
  struct DistroType<uint8_t> {
    using Type = uint16_t;
  };

  std::uniform_int_distribution<typename DistroType<Key>::Type> rnd_distro_{
      0, std::numeric_limits<Key>::max()};
  std::default_random_engine rnd_;
  fbl::HashTable<Key, std::unique_ptr<HashTableVmo>> table_;
};

// Provides a `Backing` for `VmoStore` that uses any implementer of `AbstractStorage`.
// This type of `Backing` can be used if the static dispatch option provided by `VmoStore` is not
// feasible or desirable, such as providing C-bindings for `VmoStore`, for example.
// `DynamicDispatchStorage` can be used to have different backing stores decided at runtime, at the
// cost of having dynamic dispatch method calls, which can be slower than static dispatch.
//
// For example, we can have two different backing store implementations and we can decide between
// which to use at runtime, using the same `VmoStore` type:
//
// class Foo: public AbstractStorage<uint32_t> { /* ... */ }
// class Bar: public AbstractStorage<uint32_t> { /* ... */ }
// using MyVmoStore = VmoStore<DynamicDispatchStorage<uint32_t>>;
// void MyFunction(bool foo_or_bar) {
//    MyVmoStore my_store(/* ... */,
//              std::unique_ptr<AbstractStorage>(foo_or_bar ? new Foo() : new Bar());
// }
template <typename _Key, typename _Meta = void>
class DynamicDispatchStorage : public AbstractStorage<_Key, _Meta> {
 public:
  using typename AbstractStorage<_Key, _Meta>::Key;
  using typename AbstractStorage<_Key, _Meta>::Meta;
  using Item = StoredVmo<Meta>;
  using Base = AbstractStorage<Key, Meta>;
  using BasePtr = std::unique_ptr<Base>;

  explicit DynamicDispatchStorage(BasePtr impl) : impl_(std::move(impl)) {}

  inline zx_status_t Reserve(size_t capacity) override { return impl_->Reserve(capacity); }
  inline zx_status_t Insert(Key key, Item&& vmo) override {
    return impl_->Insert(std::move(key), std::move(vmo));
  }
  inline cpp17::optional<Key> Push(Item&& vmo) override { return impl_->Push(std::move(vmo)); }
  inline Item* Get(const Key& key) override { return impl_->Get(key); }
  cpp17::optional<Item> Extract(Key key) override { return impl_->Extract(std::move(key)); }
  inline size_t count() const override { return impl_->count(); }
  inline bool is_full() const override { return impl_->is_full(); }

 private:
  BasePtr impl_;
};

namespace internal {
// Helpers for static assertions to detect type members.
DECLARE_HAS_MEMBER_TYPE(has_key, Key);
DECLARE_HAS_MEMBER_TYPE(has_meta, Meta);

#define DECLARE_MEMBER_TYPE_FALLBACK(trait_name, member, check, fallback)  \
  template <typename T>                                                    \
  struct trait_name {                                                      \
   private:                                                                \
    template <typename C, typename std::enable_if_t<check<C>>* = nullptr>  \
    static typename C::member test();                                      \
    template <typename C, typename std::enable_if_t<!check<C>>* = nullptr> \
    static fallback test();                                                \
                                                                           \
   public:                                                                 \
    using type = decltype(test<T>());                                      \
  };  // namespace internal

// These provide better errors for is_abstract_storage, avoiding "Undeclared identifier Key|Meta"
// error messages.
DECLARE_MEMBER_TYPE_FALLBACK(key_for, Key, has_key_v, size_t)
DECLARE_MEMBER_TYPE_FALLBACK(meta_for, Meta, has_meta_v, void)

template <typename T>
static inline constexpr bool is_abstract_storage = std::is_convertible<
    T*, AbstractStorage<typename key_for<T>::type, typename meta_for<T>::type>*>::value;
}  // namespace internal

}  // namespace vmo_store

#endif  // SRC_LIB_VMO_STORE_STORAGE_TYPES_H_
