Bug 1890277: part 2) Add `require-trusted-types-for` directive to CSP parser, guarded...
[gecko.git] / mfbt / EnumTypeTraits.h
blob09ead3d0e96a2efe6478059c8f38e5900ba7ee17
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* Type traits for enums. */
8 #ifndef mozilla_EnumTypeTraits_h
9 #define mozilla_EnumTypeTraits_h
11 #include <stddef.h>
12 #include <type_traits>
14 namespace mozilla {
16 namespace detail {
18 template <size_t EnumSize, bool EnumSigned, size_t StorageSize,
19 bool StorageSigned>
20 struct EnumFitsWithinHelper;
22 // Signed enum, signed storage.
23 template <size_t EnumSize, size_t StorageSize>
24 struct EnumFitsWithinHelper<EnumSize, true, StorageSize, true>
25 : public std::integral_constant<bool, (EnumSize <= StorageSize)> {};
27 // Signed enum, unsigned storage.
28 template <size_t EnumSize, size_t StorageSize>
29 struct EnumFitsWithinHelper<EnumSize, true, StorageSize, false>
30 : public std::integral_constant<bool, false> {};
32 // Unsigned enum, signed storage.
33 template <size_t EnumSize, size_t StorageSize>
34 struct EnumFitsWithinHelper<EnumSize, false, StorageSize, true>
35 : public std::integral_constant<bool, (EnumSize * 2 <= StorageSize)> {};
37 // Unsigned enum, unsigned storage.
38 template <size_t EnumSize, size_t StorageSize>
39 struct EnumFitsWithinHelper<EnumSize, false, StorageSize, false>
40 : public std::integral_constant<bool, (EnumSize <= StorageSize)> {};
42 } // namespace detail
45 * Type trait that determines whether the enum type T can fit within the
46 * integral type Storage without data loss. This trait should be used with
47 * caution with an enum type whose underlying type has not been explicitly
48 * specified: for such enums, the C++ implementation is free to choose a type
49 * no smaller than int whose range encompasses all possible values of the enum.
50 * So for an enum with only small non-negative values, the underlying type may
51 * be either int or unsigned int, depending on the whims of the implementation.
53 template <typename T, typename Storage>
54 struct EnumTypeFitsWithin
55 : public detail::EnumFitsWithinHelper<
56 sizeof(T),
57 std::is_signed<typename std::underlying_type<T>::type>::value,
58 sizeof(Storage), std::is_signed<Storage>::value> {
59 static_assert(std::is_enum<T>::value, "must provide an enum type");
60 static_assert(std::is_integral<Storage>::value,
61 "must provide an integral type");
64 /**
65 * Get the underlying value of an enum, but typesafe.
67 * example:
69 * enum class Pet : int16_t {
70 * Cat,
71 * Dog,
72 * Fish
73 * };
74 * enum class Plant {
75 * Flower,
76 * Tree,
77 * Vine
78 * };
79 * UnderlyingValue(Pet::Fish) -> int16_t(2)
80 * UnderlyingValue(Plant::Tree) -> int(1)
82 template <typename T>
83 inline constexpr auto UnderlyingValue(const T v) {
84 static_assert(std::is_enum_v<T>);
85 return static_cast<typename std::underlying_type<T>::type>(v);
89 * Specialize either MaxContiguousEnumValue or MaxEnumValue to provide the
90 * highest enum member value for an enum class. Note that specializing
91 * MaxContiguousEnumValue will make MaxEnumValue just take its value from the
92 * MaxContiguousEnumValue specialization.
94 * Specialize MinContiguousEnumValue and MaxContiguousEnumValue to provide both
95 * lowest and highest enum member values for an enum class with contiguous
96 * values.
98 * Each specialization of these structs should define "static constexpr" member
99 * variable named "value".
101 * example:
103 * enum ExampleEnum
105 * CAT = 0,
106 * DOG,
107 * HAMSTER
108 * };
110 * template <>
111 * struct MaxEnumValue<ExampleEnum>
113 * static constexpr ExampleEnumvalue = HAMSTER;
114 * };
117 template <typename T>
118 struct MinContiguousEnumValue {
119 static constexpr T value = static_cast<T>(0);
122 template <typename T>
123 struct MaxContiguousEnumValue;
125 template <typename T>
126 struct MaxEnumValue {
127 static constexpr auto value = MaxContiguousEnumValue<T>::value;
130 // Provides the min and max values for a contiguous enum (requires at least
131 // MaxContiguousEnumValue to be defined).
132 template <typename T>
133 struct ContiguousEnumValues {
134 static constexpr auto min = MinContiguousEnumValue<T>::value;
135 static constexpr auto max = MaxContiguousEnumValue<T>::value;
138 // Provides the total number of values for a contiguous enum (requires at least
139 // MaxContiguousEnumValue to be defined).
140 template <typename T>
141 struct ContiguousEnumSize {
142 static constexpr size_t value =
143 UnderlyingValue(ContiguousEnumValues<T>::max) + 1 -
144 UnderlyingValue(ContiguousEnumValues<T>::min);
147 } // namespace mozilla
149 #endif /* mozilla_EnumTypeTraits_h */