chromium/third_party/dawn/src/tint/utils/rtti/castable.h

// Copyright 2020 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_UTILS_RTTI_CASTABLE_H_
#define SRC_TINT_UTILS_RTTI_CASTABLE_H_

#include <stdint.h>
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>

#include "src/tint/utils/macros/compiler.h"
#include "src/tint/utils/math/crc32.h"
#include "src/tint/utils/math/hash.h"
#include "src/tint/utils/rtti/ignore.h"
#include "src/tint/utils/traits/traits.h"

#if defined(__clang__)
/// Temporarily disable certain warnings when using Castable API
#define TINT_CASTABLE_PUSH_DISABLE_WARNINGS()

/// Restore disabled warnings
#define TINT_CASTABLE_POP_DISABLE_WARNINGS()
#else
#define TINT_CASTABLE_PUSH_DISABLE_WARNINGS
#define TINT_CASTABLE_POP_DISABLE_WARNINGS
#endif

TINT_CASTABLE_PUSH_DISABLE_WARNINGS();

// Forward declarations
namespace tint {
class CastableBase;
}  // namespace tint

namespace tint::detail {
template <typename T>
struct TypeInfoOf;
}  // namespace tint::detail

namespace tint {

/// True if all template types that are not Ignore derive from CastableBase
IsCastable;

/// Helper macro to instantiate the TypeInfo<T> template for `CLASS`.
#define TINT_INSTANTIATE_TYPEINFO(CLASS)

/// Bit flags that can be passed to the template parameter `FLAGS` of Is() and As().
enum CastFlags {};

/// TypeCode is a bit pattern used by Tint's RTTI system to determine whether two types are related
/// by inheritance.
/// Each TypeCode has exactly two bits set.
struct TypeCode {};

/// TypeCodeSet is a set of TypeCodes, and internally uses a single integer to represent its
/// contents. TypeCodeSet acts as a bloom-filter, exposing methods to query whether the set _may_
/// contain one or more TypeCodes. If these methods return `false` then the set definitely does
/// contain the TypeCode(s), however returning `true` means the *set has a possibility* of
/// containing the TypeCodes(s).
/// @see https://en.wikipedia.org/wiki/Bloom_filter
struct TypeCodeSet {};

/// TypeInfo holds type information for a Castable type.
struct TypeInfo {};

namespace detail {

/// TypeInfoOf contains a single TypeInfo field for the type T.
/// TINT_INSTANTIATE_TYPEINFO() must be defined in a .cpp file for each type `T`.
template <typename T>
struct TypeInfoOf {};

/// A placeholder structure used for template parameters that need a default type, but can always be
/// automatically inferred.
struct Infer;

}  // namespace detail

/// @returns true if `obj` is a valid pointer, and is of, or derives from the class `TO`
/// @param obj the object to test from
/// @see CastFlags
template <typename TO, int FLAGS = 0, typename FROM = tint::detail::Infer>
inline bool Is(FROM* obj) {}

/// @returns true if `obj` is a valid pointer, and is of, or derives from the type `TYPE`, and
/// pred(const TYPE*) returns true
/// @param obj the object to test from
/// @param pred predicate function with signature `bool(const TYPE*)` called iff object is of, or
/// derives from the class `TYPE`.
/// @see CastFlags
template <typename TYPE,
          int FLAGS = 0,
          typename OBJ = tint::detail::Infer,
          typename Pred = tint::detail::Infer>
inline bool Is(OBJ* obj, Pred&& pred) {}

/// @returns true if `obj` is a valid pointer, and is of, or derives from any of the types in
/// `TYPES`.
/// @param obj the object to query.
template <typename... TYPES, typename OBJ>
inline bool IsAnyOf(OBJ* obj) {}

/// @returns obj dynamically cast to the type `TO` or `nullptr` if this object does not derive from
/// `TO`.
/// @param obj the object to cast from
/// @see CastFlags
template <typename TO, int FLAGS = 0, typename FROM = tint::detail::Infer>
inline TO* As(FROM* obj) {}

/// @returns obj dynamically cast to the type `TO` or `nullptr` if this object does not derive from
/// `TO`.
/// @param obj the object to cast from
/// @see CastFlags
template <typename TO, int FLAGS = 0, typename FROM = tint::detail::Infer>
inline const TO* As(const FROM* obj) {}

/// CastableBase is the base class for all Castable objects.
/// It is not encouraged to directly derive from CastableBase without using the Castable helper
/// template.
/// @see Castable
class CastableBase {};

/// Castable is a helper to derive `CLASS` from `BASE`, automatically implementing the Is() and As()
/// methods, along with a #Base type alias.
///
/// Example usage:
///
/// ```
/// class Animal : public Castable<Animal> {};
///
/// class Sheep : public Castable<Sheep, Animal> {};
///
/// Sheep* cast_to_sheep(Animal* animal) {
///    // You can query whether a Castable is of the given type with Is<T>():
///    printf("animal is a sheep? %s", animal->Is<Sheep>() ? "yes" : "no");
///
///    // You can always just try the cast with As<T>().
///    // If the object is not of the correct type, As<T>() will return nullptr:
///    return animal->As<Sheep>();
/// }
/// ```
template <typename CLASS, typename BASE = CastableBase>
class Castable : public BASE {};

namespace detail {
/// <code>typename CastableCommonBaseImpl<TYPES>::type</code> resolves to the common base class for
/// all of TYPES.
template <typename... TYPES>
struct CastableCommonBaseImpl {};

/// Alias to typename CastableCommonBaseImpl<TYPES>::type
CastableCommonBase;

/// CastableCommonBaseImpl template specialization for a single type
CastableCommonBaseImpl<T>;

/// CastableCommonBaseImpl A <-> CastableBase specialization
CastableCommonBaseImpl<A, CastableBase>;

/// CastableCommonBaseImpl T <-> Ignore specialization
CastableCommonBaseImpl<T, Ignore>;

/// CastableCommonBaseImpl Ignore <-> T specialization
CastableCommonBaseImpl<Ignore, T>;

/// CastableCommonBaseImpl A <-> B specialization
CastableCommonBaseImpl<A, B>;

/// CastableCommonBaseImpl 3+ types specialization
CastableCommonBaseImpl<A, B, OTHERS...>;

}  // namespace detail

/// Resolves to the common most derived type that each of the types in `TYPES` derives from.
CastableCommonBase;

}  // namespace tint

namespace tint {

As;
Is;

}  // namespace tint

TINT_CASTABLE_POP_DISABLE_WARNINGS();

#endif  // SRC_TINT_UTILS_RTTI_CASTABLE_H_