1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef __IPC_GLUE_ENUMSERIALIZER_H__
8 #define __IPC_GLUE_ENUMSERIALIZER_H__
10 #include "CrashAnnotations.h"
11 #include "chrome/common/ipc_message_utils.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/IntegerTypeTraits.h"
14 #include "nsExceptionHandler.h"
15 #include "nsLiteralString.h"
17 #include "nsTLiteralString.h"
28 # pragma warning(disable : 4800)
34 * Generic enum serializer.
36 * Consider using the specializations below, such as ContiguousEnumSerializer.
38 * This is a generic serializer for any enum type used in IPDL.
39 * Programmers can define ParamTraits<E> for enum type E by deriving
40 * EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
41 * that has to define a static IsLegalValue function returning whether
42 * a given value is a legal value of the enum type at hand.
44 * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
46 template <typename E
, typename EnumValidator
>
47 struct EnumSerializer
{
50 // XXX(Bug 1690343) Should this be changed to
51 // std::make_unsigned_t<std::underlying_type_t<paramType>>, to make this more
52 // consistent with the type used for validating values?
53 typedef typename
mozilla::UnsignedStdintTypeForSize
<sizeof(paramType
)>::Type
56 static void Write(MessageWriter
* aWriter
, const paramType
& aValue
) {
57 // XXX This assertion is somewhat meaningless at least for E that don't have
58 // a fixed underlying type: if aValue weren't a legal value, we would
59 // already have UB where this function is called.
60 MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(
61 static_cast<std::underlying_type_t
<paramType
>>(aValue
)));
62 WriteParam(aWriter
, uintParamType(aValue
));
65 static bool Read(MessageReader
* aReader
, paramType
* aResult
) {
67 if (!ReadParam(aReader
, &value
)) {
68 CrashReporter::AnnotateCrashReport(
69 CrashReporter::Annotation::IPCReadErrorReason
, "Bad iter"_ns
);
71 } else if (!EnumValidator::IsLegalValue(value
)) {
72 CrashReporter::AnnotateCrashReport(
73 CrashReporter::Annotation::IPCReadErrorReason
, "Illegal value"_ns
);
76 *aResult
= paramType(value
);
81 template <typename E
, E MinLegal
, E HighBound
>
82 class ContiguousEnumValidator
{
83 // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
84 // "comparison of unsigned expression >= 0 is always true"
85 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
87 static bool IsLessThanOrEqual(T a
, T b
) {
92 using IntegralType
= std::underlying_type_t
<E
>;
93 static constexpr auto kMinLegalIntegral
= static_cast<IntegralType
>(MinLegal
);
94 static constexpr auto kHighBoundIntegral
=
95 static_cast<IntegralType
>(HighBound
);
97 static bool IsLegalValue(const IntegralType e
) {
98 return IsLessThanOrEqual(kMinLegalIntegral
, e
) && e
< kHighBoundIntegral
;
102 template <typename E
, E MinLegal
, E MaxLegal
>
103 class ContiguousEnumValidatorInclusive
{
104 // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
105 // "comparison of unsigned expression >= 0 is always true"
106 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
107 template <typename T
>
108 static bool IsLessThanOrEqual(T a
, T b
) {
113 using IntegralType
= std::underlying_type_t
<E
>;
114 static constexpr auto kMinLegalIntegral
= static_cast<IntegralType
>(MinLegal
);
115 static constexpr auto kMaxLegalIntegral
= static_cast<IntegralType
>(MaxLegal
);
117 static bool IsLegalValue(const IntegralType e
) {
118 return IsLessThanOrEqual(kMinLegalIntegral
, e
) && e
<= kMaxLegalIntegral
;
122 template <typename E
, E AllBits
>
123 struct BitFlagsEnumValidator
{
124 static bool IsLegalValue(const std::underlying_type_t
<E
> e
) {
125 return (e
& static_cast<std::underlying_type_t
<E
>>(AllBits
)) == e
;
130 * Specialization of EnumSerializer for enums with contiguous enum values.
132 * Provide two values: MinLegal, HighBound. An enum value x will be
133 * considered legal if MinLegal <= x < HighBound.
135 * For example, following is definition of serializer for enum type FOO.
137 * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
140 * struct ParamTraits<FOO>:
141 * public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
143 * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
145 template <typename E
, E MinLegal
, E HighBound
>
146 struct ContiguousEnumSerializer
147 : EnumSerializer
<E
, ContiguousEnumValidator
<E
, MinLegal
, HighBound
>> {};
150 * This is similar to ContiguousEnumSerializer, but the last template
151 * parameter is expected to be the highest legal value, rather than a
152 * sentinel value. This is intended to support enumerations that don't
153 * have sentinel values.
155 template <typename E
, E MinLegal
, E MaxLegal
>
156 struct ContiguousEnumSerializerInclusive
158 ContiguousEnumValidatorInclusive
<E
, MinLegal
, MaxLegal
>> {
162 * Specialization of EnumSerializer for enums representing bit flags.
164 * Provide one value: AllBits. An enum value x will be
165 * considered legal if (x & AllBits) == x;
170 * FOO_FIRST = 1 << 0,
171 * FOO_SECOND = 1 << 1,
173 * ALL_BITS = (1 << 3) - 1
177 * struct ParamTraits<FOO>:
178 * public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
181 template <typename E
, E AllBits
>
182 struct BitFlagsEnumSerializer
183 : EnumSerializer
<E
, BitFlagsEnumValidator
<E
, AllBits
>> {};
185 } /* namespace IPC */
187 #endif /* __IPC_GLUE_ENUMSERIALIZER_H__ */