/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H
#define GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H

// manually construct a region of memory with some type

#include <grpc/support/port_platform.h>

#include <stddef.h>
#include <stdlib.h>
#include <new>
#include <type_traits>
#include <utility>

#include <grpc/support/log.h>

namespace grpc_core {

// this contains templated helpers needed to implement the ManualConstructors
// in this file.
namespace manual_ctor_impl {

// is_one_of returns true it a class, Member, is present in a variadic list of
// classes, List.
template <class Member, class... List>
class is_one_of;

template <class Member, class... List>
class is_one_of<Member, Member, List...> {
 public:
  static constexpr const bool value = true;
};

template <class Member, class A, class... List>
class is_one_of<Member, A, List...> {
 public:
  static constexpr const bool value = is_one_of<Member, List...>::value;
};

template <class Member>
class is_one_of<Member> {
 public:
  static constexpr const bool value = false;
};

// max_size_of returns sizeof(Type) for the largest type in the variadic list
// of classes, Types.
template <class... Types>
class max_size_of;

template <class A>
class max_size_of<A> {
 public:
  static constexpr const size_t value = sizeof(A);
};

template <class A, class... B>
class max_size_of<A, B...> {
 public:
  static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
                                            ? sizeof(A)
                                            : max_size_of<B...>::value;
};

// max_size_of returns alignof(Type) for the largest type in the variadic list
// of classes, Types.
template <class... Types>
class max_align_of;

template <class A>
class max_align_of<A> {
 public:
  static constexpr const size_t value = alignof(A);
};

template <class A, class... B>
class max_align_of<A, B...> {
 public:
  static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
                                            ? alignof(A)
                                            : max_align_of<B...>::value;
};

}  // namespace manual_ctor_impl

template <class BaseType, class... DerivedTypes>
class PolymorphicManualConstructor {
 public:
  // No constructor or destructor because one of the most useful uses of
  // this class is as part of a union, and members of a union could not have
  // constructors or destructors till C++11.  And, anyway, the whole point of
  // this class is to bypass constructor and destructor.

  BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
  const BaseType* get() const {
    return reinterpret_cast<const BaseType*>(&space_);
  }

  BaseType* operator->() { return get(); }
  const BaseType* operator->() const { return get(); }

  BaseType& operator*() { return *get(); }
  const BaseType& operator*() const { return *get(); }

  template <class DerivedType>
  void Init() {
    FinishInit(new (&space_) DerivedType);
  }

  // Init() constructs the Type instance using the given arguments
  // (which are forwarded to Type's constructor).
  //
  // Note that Init() with no arguments performs default-initialization,
  // not zero-initialization (i.e it behaves the same as "new Type;", not
  // "new Type();"), so it will leave non-class types uninitialized.
  template <class DerivedType, typename... Ts>
  void Init(Ts&&... args) {
    FinishInit(new (&space_) DerivedType(std::forward<Ts>(args)...));
  }

  // Init() that is equivalent to copy and move construction.
  // Enables usage like this:
  //   ManualConstructor<std::vector<int>> v;
  //   v.Init({1, 2, 3});
  template <class DerivedType>
  void Init(const DerivedType& x) {
    FinishInit(new (&space_) DerivedType(x));
  }
  template <class DerivedType>
  void Init(DerivedType&& x) {
    FinishInit(new (&space_) DerivedType(std::move(x)));
  }

  void Destroy() { get()->~BaseType(); }

 private:
  template <class DerivedType>
  void FinishInit(DerivedType* p) {
    static_assert(
        manual_ctor_impl::is_one_of<DerivedType, DerivedTypes...>::value,
        "DerivedType must be one of the predeclared DerivedTypes");
    GPR_ASSERT(static_cast<BaseType*>(p) == p);
  }

  typename std::aligned_storage<
      grpc_core::manual_ctor_impl::max_size_of<DerivedTypes...>::value,
      grpc_core::manual_ctor_impl::max_align_of<DerivedTypes...>::value>::type
      space_;
};

template <typename Type>
class ManualConstructor {
 public:
  // No constructor or destructor because one of the most useful uses of
  // this class is as part of a union, and members of a union could not have
  // constructors or destructors till C++11.  And, anyway, the whole point of
  // this class is to bypass constructor and destructor.

  Type* get() { return reinterpret_cast<Type*>(&space_); }
  const Type* get() const { return reinterpret_cast<const Type*>(&space_); }

  Type* operator->() { return get(); }
  const Type* operator->() const { return get(); }

  Type& operator*() { return *get(); }
  const Type& operator*() const { return *get(); }

  void Init() { new (&space_) Type; }

  // Init() constructs the Type instance using the given arguments
  // (which are forwarded to Type's constructor).
  //
  // Note that Init() with no arguments performs default-initialization,
  // not zero-initialization (i.e it behaves the same as "new Type;", not
  // "new Type();"), so it will leave non-class types uninitialized.
  template <typename... Ts>
  void Init(Ts&&... args) {
    new (&space_) Type(std::forward<Ts>(args)...);
  }

  // Init() that is equivalent to copy and move construction.
  // Enables usage like this:
  //   ManualConstructor<std::vector<int>> v;
  //   v.Init({1, 2, 3});
  void Init(const Type& x) { new (&space_) Type(x); }
  void Init(Type&& x) { new (&space_) Type(std::move(x)); }

  void Destroy() { get()->~Type(); }

 private:
  typename std::aligned_storage<sizeof(Type), alignof(Type)>::type space_;
};

}  // namespace grpc_core

#endif
