// Copyright 2018 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_NULLABLE_H_
#define LIB_FIT_NULLABLE_H_

#include <assert.h>

#include <type_traits>
#include <utility>

#include "optional.h"

namespace fit {

// Determines whether a type can be compared with nullptr.
template <typename T, typename Comparable = bool>
struct is_comparable_with_null : public std::false_type {};
template <typename T>
struct is_comparable_with_null<T, decltype(std::declval<const T&>() == nullptr)>
    : public std::true_type {};

// Suppress the warning when the compiler can see that a nullable value is
// never equal to nullptr.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
template <typename T, std::enable_if_t<is_comparable_with_null<T>::value, bool> = true>
constexpr inline bool is_null(T&& value) {
  return std::forward<T>(value) == nullptr;
}
#pragma GCC diagnostic pop

template <typename T, std::enable_if_t<!is_comparable_with_null<T>::value, bool> = false>
constexpr inline bool is_null(T&&) {
  return false;
}

// Determines whether a type can be initialized, assigned, and compared
// with nullptr.
template <typename T>
struct is_nullable
    : public std::integral_constant<bool, std::is_constructible<T, decltype(nullptr)>::value &&
                                              std::is_assignable<T&, decltype(nullptr)>::value &&
                                              is_comparable_with_null<T>::value> {};
template <>
struct is_nullable<void> : public std::false_type {};

// Holds a value or nullptr.
//
// This class is similar to |std::optional<T>| except that it uses less
// storage when the value type can be initialized, assigned, and compared
// with nullptr.
//
// For example:
// - sizeof(fit::nullable<void*>) == sizeof(void*)
// - sizeof(std::optional<void*>) == sizeof(struct { bool; void*; })
// - sizeof(fit::nullable<int>) == sizeof(struct { bool; int; })
// - sizeof(std::optional<int>) == sizeof(struct { bool; int; })
//
// TODO(CF-806): fit::nullable does not precisely mirror fit::optional now that
// fit::optional is closer to standards compliant. This should be corrected to
// avoid surprises when switching between the types.
template <typename T, bool = (is_nullable<T>::value && std::is_constructible<T, T&&>::value &&
                              std::is_assignable<T&, T&&>::value)>
class nullable final {
 public:
  using value_type = T;

  ~nullable() = default;
  constexpr nullable() = default;

  explicit constexpr nullable(decltype(nullptr)) {}
  explicit constexpr nullable(T value) : opt_(std::move(value)) {}

  constexpr nullable(const nullable& other) = default;
  constexpr nullable& operator=(const nullable& other) = default;

  constexpr nullable(nullable&& other) = default;
  constexpr nullable& operator=(nullable&& other) = default;

  constexpr T& value() & { return opt_.value(); }
  constexpr const T& value() const& { return opt_.value(); }
  constexpr T&& value() && { return std::move(opt_.value()); }
  constexpr const T&& value() const&& { return std::move(opt_.value()); }

  template <typename U = T>
  constexpr T value_or(U&& default_value) const {
    return opt_.value_or(std::forward<U>(default_value));
  }

  constexpr T* operator->() { return &*opt_; }
  constexpr const T* operator->() const { return &*opt_; }
  constexpr T& operator*() { return *opt_; }
  constexpr const T& operator*() const { return *opt_; }

  constexpr bool has_value() const { return opt_.has_value(); }
  explicit constexpr operator bool() const { return has_value(); }

  constexpr nullable& operator=(decltype(nullptr)) {
    reset();
    return *this;
  }

  constexpr nullable& operator=(T value) {
    opt_ = std::move(value);
    return *this;
  }

  constexpr void reset() { opt_.reset(); }

  constexpr void swap(nullable& other) { opt_.swap(other.opt_); }

 private:
  optional<T> opt_;
};

template <typename T>
class nullable<T, true> final {
 public:
  using value_type = T;

  constexpr nullable() : value_(nullptr) {}
  explicit constexpr nullable(decltype(nullptr)) : value_(nullptr) {}
  explicit constexpr nullable(T value) : value_(std::move(value)) {}
  constexpr nullable(const nullable& other) = default;
  constexpr nullable(nullable&& other) : value_(std::move(other.value_)) {}
  ~nullable() = default;

  constexpr T& value() & {
    if (has_value()) {
      return value_;
    } else {
      __builtin_abort();
    }
  }
  constexpr const T& value() const& {
    if (has_value()) {
      return value_;
    } else {
      __builtin_abort();
    }
  }
  constexpr T&& value() && {
    if (has_value()) {
      return std::move(value_);
    } else {
      __builtin_abort();
    }
  }
  constexpr const T&& value() const&& {
    if (has_value()) {
      return std::move(value_);
    } else {
      __builtin_abort();
    }
  }

  template <typename U = T>
  constexpr T value_or(U&& default_value) const {
    return has_value() ? value_ : static_cast<T>(std::forward<U>(default_value));
  }

  constexpr T* operator->() { return &value_; }
  constexpr const T* operator->() const { return &value_; }
  constexpr T& operator*() { return value_; }
  constexpr const T& operator*() const { return value_; }

  constexpr bool has_value() const { return !(value_ == nullptr); }
  explicit constexpr operator bool() const { return has_value(); }

  constexpr nullable& operator=(const nullable& other) = default;
  constexpr nullable& operator=(nullable&& other) {
    value_ = std::move(other.value_);
    return *this;
  }

  constexpr nullable& operator=(decltype(nullptr)) {
    reset();
    return *this;
  }

  constexpr nullable& operator=(T value) {
    value_ = std::move(value);
    return *this;
  }

  constexpr void reset() { value_ = nullptr; }

  constexpr void swap(nullable& other) {
    using std::swap;
    swap(value_, other.value_);
  }

 private:
  T value_;
};

template <typename T>
void swap(nullable<T>& a, nullable<T>& b) {
  a.swap(b);
}

template <typename T>
constexpr bool operator==(const nullable<T>& lhs, decltype(nullptr)) {
  return !lhs.has_value();
}
template <typename T>
constexpr bool operator!=(const nullable<T>& lhs, decltype(nullptr)) {
  return lhs.has_value();
}

template <typename T>
constexpr bool operator==(decltype(nullptr), const nullable<T>& rhs) {
  return !rhs.has_value();
}
template <typename T>
constexpr bool operator!=(decltype(nullptr), const nullable<T>& rhs) {
  return rhs.has_value();
}

template <typename T, typename U>
constexpr bool operator==(const nullable<T>& lhs, const nullable<U>& rhs) {
  return (lhs.has_value() == rhs.has_value()) && (!lhs.has_value() || *lhs == *rhs);
}
template <typename T, typename U>
constexpr bool operator!=(const nullable<T>& lhs, const nullable<U>& rhs) {
  return (lhs.has_value() != rhs.has_value()) || (lhs.has_value() && *lhs != *rhs);
}

template <typename T, typename U>
constexpr bool operator==(const nullable<T>& lhs, const U& rhs) {
  return (lhs.has_value() != is_null(rhs)) && (!lhs.has_value() || *lhs == rhs);
}
template <typename T, typename U>
constexpr bool operator!=(const nullable<T>& lhs, const U& rhs) {
  return (lhs.has_value() == is_null(rhs)) || (lhs.has_value() && *lhs != rhs);
}

template <typename T, typename U>
constexpr bool operator==(const T& lhs, const nullable<U>& rhs) {
  return (is_null(lhs) != rhs.has_value()) && (!rhs.has_value() || lhs == *rhs);
}
template <typename T, typename U>
constexpr bool operator!=(const T& lhs, const nullable<U>& rhs) {
  return (is_null(lhs) == rhs.has_value()) || (rhs.has_value() && lhs != *rhs);
}

}  // namespace fit

#endif  // LIB_FIT_NULLABLE_H_
