// Copyright 2019 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 LIB_FIT_STORAGE_INTERNAL_H_
#define LIB_FIT_STORAGE_INTERNAL_H_

#include <cstdint>
#include <limits>
#include <type_traits>

#include "utility_internal.h"

namespace fit {
namespace internal {

// Type tag to select overloads based on type T.
template <typename T>
struct type_tag {
  using type = T;
};

// Type tag to select overloads based on index Index.
template <size_t Index>
struct index_tag {
  static constexpr size_t index = Index;
};

// Type tag to select trivial initialization.
enum trivial_init_t { trivial_init_v };

// Type tag to select default initialization.
enum default_init_t { default_init_v };

// Type tag to select conditional initialization.
enum maybe_init_t { maybe_init_v };

// Represents the pair (T, Index) in the type system.
template <typename T, size_t Index>
struct type_index {};

// Represents whether a type is trivially/non-trivially destructible.
enum class destructor_class {
  trivial,
  non_trivial,
};

// Represents whether a type is trivially/non-trivially copyable.
enum class copy_class {
  trivial,
  non_trivial,
};

// Represents whether a type is trivially/non-trivially movable.
enum class move_class {
  trivial,
  non_trivial,
};

// Represents the full complement of move/copy/destruct classes for a type.
template <destructor_class DestructorClass, copy_class CopyClass, move_class MoveClass>
struct storage_class {};

template <typename... Ts>
using make_storage_class =
    storage_class<is_trivially_destructible_v<Ts...> ? destructor_class::trivial
                                                     : destructor_class::non_trivial,
                  is_trivially_copyable_v<Ts...> ? copy_class::trivial : copy_class::non_trivial,
                  is_trivially_movable_v<Ts...> ? move_class::trivial : move_class::non_trivial>;

// A trivial type for the empty alternative of union-based storage.
struct empty_type {};

// Index type used to track the active variant. Tracking uses zero-based
// indices. Empty is denoted by the maximum representable value.
using index_type = size_t;

// Index denoting that no user-specified variant is active. Take care not to
// ODR-use this value.
constexpr index_type empty_index = std::numeric_limits<index_type>::max();

#ifdef NDEBUG
#define FIT_INTERNAL_UNREACHABLE_OR_ABORT __builtin_unreachable
#else
#define FIT_INTERNAL_UNREACHABLE_OR_ABORT __builtin_abort
#endif

// Base type for lazy-initialized union storage types. This type implements a
// recursive union of the element types in Ts. Specializations handle the
// recursive and terminal cases, and the different storage requirements for
// trivially/non-trivially destructible types.
template <destructor_class, typename...>
union storage_base;

// Non-trivial terminal case.
template <>
union storage_base<destructor_class::non_trivial, type_index<empty_type, empty_index>> {
  storage_base() : empty{} {}

  template <typename... Args>
  storage_base(type_tag<empty_type>, Args&&...) : empty{} {}
  template <typename... Args>
  storage_base(index_tag<empty_index>, Args&&...) : empty{} {}

  // Non-trivial destructor.
  ~storage_base() {}

  storage_base(const storage_base&) = default;
  storage_base(storage_base&&) = default;
  storage_base& operator=(const storage_base&) = default;
  storage_base& operator=(storage_base&&) = default;

  void construct_at(size_t index, const storage_base&) {
    if (index == empty_index) {
      new (&empty) empty_type{};
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }
  void construct_at(size_t index, storage_base&&) {
    if (index == empty_index) {
      new (&empty) empty_type{};
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  void assign_at(size_t index, const storage_base& other) {
    if (index == empty_index) {
      empty = other.empty;
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }
  void assign_at(size_t index, storage_base&& other) {
    if (index == empty_index) {
      empty = std::move(other.empty);
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  void swap_at(size_t index, storage_base& other) {
    if (index == empty_index) {
      using std::swap;
      swap(empty, other.empty);
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  template <typename... Args>
  size_t construct(type_tag<empty_type>, Args&&...) {
    new (&empty) empty_type{};
    return empty_index;
  }
  template <typename... Args>
  size_t construct(index_tag<empty_index>, Args&&...) {
    new (&empty) empty_type{};
    return empty_index;
  }

  void reset(size_t index) {
    if (index == empty_index) {
      empty.empty_type::~empty_type();
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  empty_type& get(type_tag<empty_type>) { return empty; }
  const empty_type& get(type_tag<empty_type>) const { return empty; }
  empty_type& get(index_tag<empty_index>) { return empty; }
  const empty_type& get(index_tag<empty_index>) const { return empty; }

  size_t index(type_tag<empty_type>) const { return empty_index; }

  template <typename V>
  bool visit(size_t, V&&) {
    return false;
  }
  template <typename V>
  bool visit(size_t, V&&) const {
    return false;
  }

  empty_type empty;
};

// Trivial terminal case.
template <>
union storage_base<destructor_class::trivial, type_index<empty_type, empty_index>> {
  constexpr storage_base() : empty{} {}

  template <typename... Args>
  constexpr storage_base(type_tag<empty_type>, Args&&...) : empty{} {}
  template <typename... Args>
  constexpr storage_base(index_tag<empty_index>, Args&&...) : empty{} {}

  // Trivial destructor.
  ~storage_base() = default;

  constexpr storage_base(const storage_base&) = default;
  constexpr storage_base(storage_base&&) = default;
  constexpr storage_base& operator=(const storage_base&) = default;
  constexpr storage_base& operator=(storage_base&&) = default;

  constexpr void construct_at(size_t index, const storage_base&) {
    if (index == empty_index) {
      new (&empty) empty_type{};
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }
  constexpr void construct_at(size_t index, storage_base&&) {
    if (index == empty_index) {
      new (&empty) empty_type{};
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  constexpr void assign_at(size_t index, const storage_base& other) {
    if (index == empty_index) {
      empty = other.empty;
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }
  constexpr void assign_at(size_t index, storage_base&& other) {
    if (index == empty_index) {
      empty = std::move(other.empty);
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  constexpr void swap_at(size_t index, storage_base& other) {
    if (index == empty_index) {
      using std::swap;
      swap(empty, other.empty);
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  template <typename... Args>
  constexpr size_t construct(type_tag<empty_type>, Args&&...) {
    new (&empty) empty_type{};
    return empty_index;
  }
  template <typename... Args>
  constexpr size_t construct(index_tag<empty_index>, Args&&...) {
    new (&empty) empty_type{};
    return empty_index;
  }

  constexpr void reset(size_t index) {
    if (index == empty_index) {
      empty.empty_type::~empty_type();
    } else {
      FIT_INTERNAL_UNREACHABLE_OR_ABORT();
    }
  }

  constexpr empty_type& get(type_tag<empty_type>) { return empty; }
  constexpr const empty_type& get(type_tag<empty_type>) const { return empty; }
  constexpr empty_type& get(index_tag<empty_index>) { return empty; }
  constexpr const empty_type& get(index_tag<empty_index>) const { return empty; }

  constexpr size_t index(type_tag<empty_type>) const { return empty_index; }

  template <typename V>
  constexpr bool visit(size_t, V&&) {
    return false;
  }
  template <typename V>
  constexpr bool visit(size_t, V&&) const {
    return false;
  }

  empty_type empty;
};

template <typename T, size_t Index, typename... Ts, size_t... Is>
union storage_base<destructor_class::non_trivial, type_index<T, Index>, type_index<Ts, Is>...> {
  storage_base() : empty{} {}

  template <typename... Args>
  storage_base(type_tag<T>, Args&&... args) : value(std::forward<Args>(args)...) {}
  template <typename... Args>
  storage_base(index_tag<Index>, Args&&... args) : value(std::forward<Args>(args)...) {}

  template <typename U, typename... Args>
  storage_base(type_tag<U>, Args&&... args) : rest(type_tag<U>{}, std::forward<Args>(args)...) {}
  template <size_t OtherIndex, typename... Args>
  storage_base(index_tag<OtherIndex>, Args&&... args)
      : rest(index_tag<OtherIndex>{}, std::forward<Args>(args)...) {}

  // Non-trivial destructor.
  ~storage_base() {}

  // Trival copy/move construction and assignment.
  storage_base(const storage_base&) = default;
  storage_base(storage_base&&) = default;
  storage_base& operator=(const storage_base&) = default;
  storage_base& operator=(storage_base&&) = default;

  void construct_at(size_t index, const storage_base& other) {
    if (index == Index) {
      new (&value) T{other.value};
    } else {
      rest.construct_at(index, other.rest);
    }
  }
  void construct_at(size_t index, storage_base&& other) {
    if (index == Index) {
      new (&value) T{std::move(other.value)};
    } else {
      rest.construct_at(index, std::move(other.rest));
    }
  }

  void assign_at(size_t index, const storage_base& other) {
    if (index == Index) {
      value = other.value;
    } else {
      rest.assign_at(index, other.rest);
    }
  }
  void assign_at(size_t index, storage_base&& other) {
    if (index == Index) {
      value = std::move(other.value);
    } else {
      rest.assign_at(index, std::move(other.rest));
    }
  }

  void swap_at(size_t index, storage_base& other) {
    if (index == Index) {
      using std::swap;
      swap(value, other.value);
    } else {
      rest.swap_at(index, other.rest);
    }
  }

  template <typename... Args>
  size_t construct(type_tag<T>, Args&&... args) {
    new (&value) T(std::forward<Args>(args)...);
    return Index;
  }
  template <typename U, typename... Args>
  size_t construct(type_tag<U>, Args&&... args) {
    return rest.construct(type_tag<U>{}, std::forward<Args>(args)...);
  }
  template <typename... Args>
  size_t construct(index_tag<Index>, Args&&... args) {
    new (&value) T(std::forward<Args>(args)...);
    return Index;
  }
  template <size_t OtherIndex, typename... Args>
  size_t construct(index_tag<OtherIndex>, Args&&... args) {
    return rest.construct(index_tag<OtherIndex>{}, std::forward<Args>(args)...);
  }

  void reset(size_t index) {
    if (index == Index) {
      value.~T();
    } else {
      rest.reset(index);
    }
  }

  T& get(type_tag<T>) { return value; }
  const T& get(type_tag<T>) const { return value; }
  template <typename U>
  U& get(type_tag<U>) {
    return rest.get(type_tag<U>{});
  }
  template <typename U>
  const U& get(type_tag<U>) const {
    return rest.get(type_tag<U>{});
  }
  T& get(index_tag<Index>) { return value; }
  const T& get(index_tag<Index>) const { return value; }
  template <size_t OtherIndex>
  auto& get(index_tag<OtherIndex>) {
    return rest.get(index_tag<OtherIndex>{});
  }
  template <size_t OtherIndex>
  const auto& get(index_tag<OtherIndex>) const {
    return rest.get(index_tag<OtherIndex>{});
  }

  size_t index(type_tag<T>) const { return Index; }
  template <typename U>
  size_t index(type_tag<U>) const {
    return rest.index(type_tag<U>{});
  }

  template <typename V>
  bool visit(size_t index, V&& visitor) {
    if (index == Index) {
      std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
      return true;
    } else {
      return rest.visit(index, std::forward<V>(visitor));
    }
  }
  template <typename V>
  bool visit(size_t index, V&& visitor) const {
    if (index == Index) {
      std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
      return true;
    } else {
      return rest.visit(index, std::forward<V>(visitor));
    }
  }

  empty_type empty;
  T value;
  storage_base<destructor_class::non_trivial, type_index<Ts, Is>...> rest;
};

template <typename T, size_t Index, typename... Ts, size_t... Is>
union storage_base<destructor_class::trivial, type_index<T, Index>, type_index<Ts, Is>...> {
  constexpr storage_base() : empty{} {}

  template <typename... Args>
  constexpr storage_base(type_tag<T>, Args&&... args) : value(std::forward<Args>(args)...) {}
  template <typename... Args>
  constexpr storage_base(index_tag<Index>, Args&&... args) : value(std::forward<Args>(args)...) {}

  template <typename U, typename... Args>
  constexpr storage_base(type_tag<U>, Args&&... args)
      : rest(type_tag<U>{}, std::forward<Args>(args)...) {}
  template <size_t OtherIndex, typename... Args>
  constexpr storage_base(index_tag<OtherIndex>, Args&&... args)
      : rest(index_tag<OtherIndex>{}, std::forward<Args>(args)...) {}

  // Trivial destructor.
  ~storage_base() = default;

  // Trival copy/move construction and assignment.
  constexpr storage_base(const storage_base&) = default;
  constexpr storage_base(storage_base&&) = default;
  constexpr storage_base& operator=(const storage_base&) = default;
  constexpr storage_base& operator=(storage_base&&) = default;

  constexpr void construct_at(size_t index, const storage_base& other) {
    if (index == Index) {
      new (&value) T{other.value};
    } else {
      rest.construct_at(index, other.rest);
    }
  }
  constexpr void construct_at(size_t index, storage_base&& other) {
    if (index == Index) {
      new (&value) T{std::move(other.value)};
    } else {
      rest.construct_at(index, std::move(other.rest));
    }
  }

  constexpr void assign_at(size_t index, const storage_base& other) {
    if (index == Index) {
      value = other.value;
    } else {
      rest.assign_at(index, other.rest);
    }
  }
  constexpr void assign_at(size_t index, storage_base&& other) {
    if (index == Index) {
      value = std::move(other.value);
    } else {
      rest.assign_at(index, std::move(other.rest));
    }
  }

  constexpr void swap_at(size_t index, storage_base& other) {
    if (index == Index) {
      using std::swap;
      swap(value, other.value);
    } else {
      rest.swap_at(index, other.rest);
    }
  }

  template <typename... Args>
  constexpr size_t construct(type_tag<T>, Args&&... args) {
    new (&value) T(std::forward<Args>(args)...);
    return Index;
  }
  template <typename U, typename... Args>
  constexpr size_t construct(type_tag<U>, Args&&... args) {
    return rest.construct(type_tag<U>{}, std::forward<Args>(args)...);
  }
  template <typename... Args>
  constexpr size_t construct(index_tag<Index>, Args&&... args) {
    new (&value) T(std::forward<Args>(args)...);
    return Index;
  }
  template <size_t OtherIndex, typename... Args>
  constexpr size_t construct(index_tag<OtherIndex>, Args&&... args) {
    return rest.construct(index_tag<OtherIndex>{}, std::forward<Args>(args)...);
  }

  constexpr void reset(size_t) {}

  constexpr T& get(type_tag<T>) { return value; }
  constexpr const T& get(type_tag<T>) const { return value; }
  template <typename U>
  constexpr U& get(type_tag<U>) {
    return rest.get(type_tag<U>{});
  }
  template <typename U>
  constexpr const U& get(type_tag<U>) const {
    return rest.get(type_tag<U>{});
  }
  constexpr T& get(index_tag<Index>) { return value; }
  constexpr const T& get(index_tag<Index>) const { return value; }
  template <size_t OtherIndex>
  constexpr auto& get(index_tag<OtherIndex>) {
    return rest.get(index_tag<OtherIndex>{});
  }
  template <size_t OtherIndex>
  constexpr const auto& get(index_tag<OtherIndex>) const {
    return rest.get(index_tag<OtherIndex>{});
  }

  constexpr size_t index(type_tag<T>) const { return Index; }
  template <typename U>
  constexpr size_t index(type_tag<U>) const {
    return rest.index(type_tag<U>{});
  }

  template <typename V>
  constexpr bool visit(size_t index, V&& visitor) {
    if (index == Index) {
      std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
      return true;
    } else {
      return rest.visit(index, std::forward<V>(visitor));
    }
  }
  template <typename V>
  constexpr bool visit(size_t index, V&& visitor) const {
    if (index == Index) {
      std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
      return true;
    } else {
      return rest.visit(index, std::forward<V>(visitor));
    }
  }

  empty_type empty;
  T value;
  storage_base<destructor_class::trivial, type_index<Ts, Is>...> rest;
};

// Lazy-initialized union storage type that tracks the index of the active
// variant.
template <destructor_class, typename...>
class indexed_storage;

template <destructor_class DestructorClass, typename... Ts, size_t... Is>
class indexed_storage<DestructorClass, type_index<Ts, Is>...> {
 private:
  using base_type =
      storage_base<DestructorClass, type_index<Ts, Is>..., type_index<empty_type, empty_index>>;

 public:
  static constexpr bool nothrow_default_constructible =
      std::is_nothrow_default_constructible<first_t<Ts...>>::value;
  static constexpr bool nothrow_move_constructible =
      conjunction_v<std::is_nothrow_move_constructible<Ts>...>;
  static constexpr bool nothrow_move_assignable =
      conjunction_v<std::is_nothrow_move_assignable<Ts>...>;

  constexpr indexed_storage() = default;

  constexpr indexed_storage(trivial_init_t) : indexed_storage{} {}

  constexpr indexed_storage(default_init_t) : index_{0}, base_{index_tag<0>{}} {}

  // Only used by trivial copy/move types.
  constexpr indexed_storage(const indexed_storage& other) = default;
  constexpr indexed_storage& operator=(const indexed_storage& other) = default;
  constexpr indexed_storage(indexed_storage&& other) = default;
  constexpr indexed_storage& operator=(indexed_storage&& other) = default;

  template <typename T, typename... Args>
  constexpr indexed_storage(type_tag<T>, Args&&... args)
      : base_(type_tag<T>{}, std::forward<Args>(args)...) {
    index_ = base_.index(type_tag<T>{});
  }
  template <size_t Index, typename... Args>
  constexpr indexed_storage(index_tag<Index>, Args&&... args)
      : index_{Index}, base_(index_tag<Index>{}, std::forward<Args>(args)...) {}

  constexpr indexed_storage(maybe_init_t, const indexed_storage& other)
      : index_{other.index()}, base_{} {
    base_.construct_at(other.index(), other.base_);
  }
  constexpr indexed_storage(maybe_init_t, indexed_storage&& other)
      : index_{other.index()}, base_{} {
    base_.construct_at(other.index(), std::move(other.base_));
  }

  ~indexed_storage() = default;

  constexpr index_type index() const { return index_; }
  constexpr bool has_value() const { return index() != empty_index; }

  template <typename T>
  constexpr auto& get(type_tag<T>) {
    return base_.get(type_tag<T>{});
  }
  template <typename T>
  constexpr const auto& get(type_tag<T>) const {
    return base_.get(type_tag<T>{});
  }
  template <size_t Index>
  constexpr auto& get(index_tag<Index>) {
    return base_.get(index_tag<Index>{});
  }
  template <size_t Index>
  constexpr const auto& get(index_tag<Index>) const {
    return base_.get(index_tag<Index>{});
  }

  template <typename T, typename... Args>
  constexpr void construct(type_tag<T>, Args&&... args) {
    index_ = base_.construct(type_tag<T>{}, std::forward<Args>(args)...);
  }
  template <size_t Index, typename... Args>
  constexpr void construct(index_tag<Index>, Args&&... args) {
    index_ = base_.construct(index_tag<Index>{}, std::forward<Args>(args)...);
  }

  constexpr void assign(const indexed_storage& other) {
    if (index() == other.index()) {
      base_.assign_at(index_, other.base_);
    } else {
      reset();
      base_.construct_at(other.index_, other.base_);
      index_ = other.index_;
    }
  }
  constexpr void assign(indexed_storage&& other) {
    if (index() == other.index()) {
      base_.assign_at(index_, std::move(other.base_));
    } else {
      reset();
      base_.construct_at(other.index_, std::move(other.base_));
      index_ = other.index_;
    }
  }

  template <typename V>
  constexpr bool visit(V&& visitor) {
    return base_.visit(index_, std::forward<V>(visitor));
  }
  template <typename V>
  constexpr bool visit(V&& visitor) const {
    return base_.visit(index_, std::forward<V>(visitor));
  }

  constexpr void swap(indexed_storage& other) {
    if (index() == other.index()) {
      // Swap directly when the variants are the same, including empty.
      base_.swap_at(index_, other.base_);
    } else {
      // Swap when the variants are different, including one being empty.
      // This approach avoids GCC -Wmaybe-uninitialized warnings by
      // initializing and accessing |temp| unconditionally within a
      // conditional scope. The alternative, using the maybe_init_t
      // constructor confuses GCC because it doesn't understand that the
      // index checks prevent uninitialized access.
      auto do_swap = [](indexed_storage& a, indexed_storage& b) {
        return a.base_.visit(a.index_, [&a, &b](auto type_tag_v, auto index_tag_v, auto* element) {
          indexed_storage temp{index_tag_v, std::move(element->value)};
          a.reset();

          a.base_.construct_at(b.index_, std::move(b.base_));
          a.index_ = b.index_;
          b.reset();

          b.base_.construct_at(temp.index_, std::move(temp.base_));
          b.index_ = temp.index_;
          temp.reset();
        });
      };

      // The visitor above returns false when the first argument is empty
      // and no action is taken. In that case, the other order is tried to
      // complete the half-empty swap.
      do_swap(*this, other) || do_swap(other, *this);
    }
  }

  // Destroys the active variant. Does nothing when already empty.
  constexpr void reset() {
    base_.reset(index_);
    index_ = empty_index;
  }

 private:
  index_type index_{empty_index};
  base_type base_;
};

// Internal variant storage type used by fit::optional and fit::variant.
// Specializations of this type select trivial vs. non-trivial copy/move
// construction, assignment operators, and destructor based on the storage class
// of the types in Ts.
template <typename StorageClass, typename... Ts>
struct storage;

template <typename... Ts, size_t... Is>
struct storage<storage_class<destructor_class::trivial, copy_class::trivial, move_class::trivial>,
               type_index<Ts, Is>...>
    : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
  using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
  using base_type::base_type;
  constexpr storage() = default;
};

template <typename... Ts, size_t... Is>
struct storage<
    storage_class<destructor_class::trivial, copy_class::non_trivial, move_class::trivial>,
    type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
  using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
  using base_type::base_type;

  ~storage() = default;
  constexpr storage() = default;

  constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}

  constexpr storage& operator=(const storage& other) {
    this->assign(other);
    return *this;
  }

  constexpr storage(storage&&) = default;
  constexpr storage& operator=(storage&&) = default;
};

template <typename... Ts, size_t... Is>
struct storage<
    storage_class<destructor_class::trivial, copy_class::trivial, move_class::non_trivial>,
    type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
  using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
  using base_type::base_type;

  ~storage() = default;
  constexpr storage() = default;
  constexpr storage(const storage&) = default;
  constexpr storage& operator=(const storage&) = default;

  constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
      : base_type{maybe_init_v, std::move(other)} {}

  constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
    this->assign(std::move(other));
    return *this;
  }
};

template <typename... Ts, size_t... Is>
struct storage<
    storage_class<destructor_class::trivial, copy_class::non_trivial, move_class::non_trivial>,
    type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
  using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
  using base_type::base_type;

  ~storage() = default;
  constexpr storage() = default;

  constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}

  constexpr storage& operator=(const storage& other) {
    this->assign(other);
    return *this;
  }

  constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
      : base_type{maybe_init_v, std::move(other)} {}

  constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
    this->assign(std::move(other));
    return *this;
  }
};

// Specialization for non-trivially movable/copyable types. Types with a non-
// trivial destructor are always non-trivially movable/copyable.
template <copy_class CopyClass, move_class MoveClass, typename... Ts, size_t... Is>
struct storage<storage_class<destructor_class::non_trivial, CopyClass, MoveClass>,
               type_index<Ts, Is>...>
    : indexed_storage<destructor_class::non_trivial, type_index<Ts, Is>...> {
  using base_type = indexed_storage<destructor_class::non_trivial, type_index<Ts, Is>...>;
  using base_type::base_type;

  ~storage() { this->reset(); }

  constexpr storage() = default;

  constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}

  constexpr storage& operator=(const storage& other) {
    this->assign(other);
    return *this;
  }

  constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
      : base_type{maybe_init_v, std::move(other)} {}

  constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
    this->assign(std::move(other));
    return *this;
  }
};

template <typename... Ts, size_t... Is>
constexpr auto make_storage(std::index_sequence<Is...>) {
  return storage<make_storage_class<Ts...>, type_index<Ts, Is>...>{};
}

template <typename... Ts>
using storage_type = decltype(make_storage<Ts...>(std::index_sequence_for<Ts...>{}));

}  // namespace internal
}  // namespace fit

#endif  // LIB_FIT_STORAGE_INTERNAL_H_
