1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __IPC_GLUE_ENUMSERIALIZER_H__
#define __IPC_GLUE_ENUMSERIALIZER_H__
#include "CrashAnnotations.h"
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/Assertions.h"
#include "mozilla/IntegerTypeTraits.h"
#include "nsExceptionHandler.h"
#include "nsLiteralString.h"
#include "nsString.h"
#include "nsTLiteralString.h"
class PickleIterator;
namespace IPC {
class Message;
class MessageReader;
class MessageWriter;
} // namespace IPC
#ifdef _MSC_VER
# pragma warning(disable : 4800)
#endif
namespace IPC {
/**
* Generic enum serializer.
*
* Consider using the specializations below, such as ContiguousEnumSerializer.
*
* This is a generic serializer for any enum type used in IPDL.
* Programmers can define ParamTraits<E> for enum type E by deriving
* EnumSerializer<E, MyEnumValidator> where MyEnumValidator is a struct
* that has to define a static IsLegalValue function returning whether
* a given value is a legal value of the enum type at hand.
*
* \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
*/
template <typename E, typename EnumValidator>
struct EnumSerializer {
typedef E paramType;
// XXX(Bug 1690343) Should this be changed to
// std::make_unsigned_t<std::underlying_type_t<paramType>>, to make this more
// consistent with the type used for validating values?
typedef typename mozilla::UnsignedStdintTypeForSize<sizeof(paramType)>::Type
uintParamType;
static void Write(MessageWriter* aWriter, const paramType& aValue) {
// XXX This assertion is somewhat meaningless at least for E that don't have
// a fixed underlying type: if aValue weren't a legal value, we would
// already have UB where this function is called.
MOZ_RELEASE_ASSERT(EnumValidator::IsLegalValue(
static_cast<std::underlying_type_t<paramType>>(aValue)));
WriteParam(aWriter, uintParamType(aValue));
}
static bool Read(MessageReader* aReader, paramType* aResult) {
uintParamType value;
if (!ReadParam(aReader, &value)) {
CrashReporter::RecordAnnotationCString(
CrashReporter::Annotation::IPCReadErrorReason, "Bad iter");
return false;
}
if (!EnumValidator::IsLegalValue(value)) {
CrashReporter::RecordAnnotationCString(
CrashReporter::Annotation::IPCReadErrorReason, "Illegal value");
return false;
}
*aResult = paramType(value);
return true;
}
};
template <typename E, E MinLegal, E HighBound>
class ContiguousEnumValidator {
// Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
// "comparison of unsigned expression >= 0 is always true"
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
template <typename T>
static bool IsLessThanOrEqual(T a, T b) {
return a <= b;
}
public:
using IntegralType = std::underlying_type_t<E>;
static constexpr auto kMinLegalIntegral = static_cast<IntegralType>(MinLegal);
static constexpr auto kHighBoundIntegral =
static_cast<IntegralType>(HighBound);
static bool IsLegalValue(const IntegralType e) {
return IsLessThanOrEqual(kMinLegalIntegral, e) && e < kHighBoundIntegral;
}
};
template <typename E, E MinLegal, E MaxLegal>
class ContiguousEnumValidatorInclusive {
// Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
// "comparison of unsigned expression >= 0 is always true"
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
template <typename T>
static bool IsLessThanOrEqual(T a, T b) {
return a <= b;
}
public:
using IntegralType = std::underlying_type_t<E>;
static constexpr auto kMinLegalIntegral = static_cast<IntegralType>(MinLegal);
static constexpr auto kMaxLegalIntegral = static_cast<IntegralType>(MaxLegal);
static bool IsLegalValue(const IntegralType e) {
return IsLessThanOrEqual(kMinLegalIntegral, e) && e <= kMaxLegalIntegral;
}
};
template <typename E, E AllBits>
struct BitFlagsEnumValidator {
static bool IsLegalValue(const std::underlying_type_t<E> e) {
return (e & static_cast<std::underlying_type_t<E>>(AllBits)) == e;
}
};
/**
* Specialization of EnumSerializer for enums with contiguous enum values.
*
* Provide two values: MinLegal, HighBound. An enum value x will be
* considered legal if MinLegal <= x < HighBound.
*
* For example, following is definition of serializer for enum type FOO.
* \code
* enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
*
* template <>
* struct ParamTraits<FOO>:
* public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
* \endcode
* FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
*/
template <typename E, E MinLegal, E HighBound>
struct ContiguousEnumSerializer
: EnumSerializer<E, ContiguousEnumValidator<E, MinLegal, HighBound>> {};
/**
* This is similar to ContiguousEnumSerializer, but the last template
* parameter is expected to be the highest legal value, rather than a
* sentinel value. This is intended to support enumerations that don't
* have sentinel values.
*/
template <typename E, E MinLegal, E MaxLegal>
struct ContiguousEnumSerializerInclusive
: EnumSerializer<E,
ContiguousEnumValidatorInclusive<E, MinLegal, MaxLegal>> {
};
/**
* Specialization of EnumSerializer for enums representing bit flags.
*
* Provide one value: AllBits. An enum value x will be
* considered legal if (x & AllBits) == x;
*
* Example:
* \code
* enum FOO {
* FOO_FIRST = 1 << 0,
* FOO_SECOND = 1 << 1,
* FOO_LAST = 1 << 2,
* ALL_BITS = (1 << 3) - 1
* };
*
* template <>
* struct ParamTraits<FOO>:
* public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
* \endcode
*/
template <typename E, E AllBits>
struct BitFlagsEnumSerializer
: EnumSerializer<E, BitFlagsEnumValidator<E, AllBits>> {};
} /* namespace IPC */
#endif /* __IPC_GLUE_ENUMSERIALIZER_H__ */
|