tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

EnumSerializer.h (6155B)


      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/. */
      6 
      7 #ifndef __IPC_GLUE_ENUMSERIALIZER_H__
      8 #define __IPC_GLUE_ENUMSERIALIZER_H__
      9 
     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"
     16 #include "nsString.h"
     17 #include "nsTLiteralString.h"
     18 
     19 class PickleIterator;
     20 
     21 namespace IPC {
     22 class Message;
     23 class MessageReader;
     24 class MessageWriter;
     25 }  // namespace IPC
     26 
     27 #ifdef _MSC_VER
     28 #  pragma warning(disable : 4800)
     29 #endif
     30 
     31 namespace IPC {
     32 
     33 /**
     34 * Generic enum serializer.
     35 *
     36 * Consider using the specializations below, such as ContiguousEnumSerializer.
     37 *
     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.
     43 *
     44 * \sa https://developer.mozilla.org/en/IPDL/Type_Serialization
     45 */
     46 template <typename E, typename EnumValidator>
     47 struct EnumSerializer {
     48  typedef E paramType;
     49 
     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
     54      uintParamType;
     55 
     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));
     63  }
     64 
     65  static bool Read(MessageReader* aReader, paramType* aResult) {
     66    uintParamType value;
     67    if (!ReadParam(aReader, &value)) {
     68      CrashReporter::RecordAnnotationCString(
     69          CrashReporter::Annotation::IPCReadErrorReason, "Bad iter");
     70      return false;
     71    }
     72    if (!EnumValidator::IsLegalValue(value)) {
     73      CrashReporter::RecordAnnotationCString(
     74          CrashReporter::Annotation::IPCReadErrorReason, "Illegal value");
     75      return false;
     76    }
     77    *aResult = paramType(value);
     78    return true;
     79  }
     80 };
     81 
     82 template <typename E, E MinLegal, E HighBound>
     83 class ContiguousEnumValidator {
     84  // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
     85  // "comparison of unsigned expression >= 0 is always true"
     86  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
     87  template <typename T>
     88  static bool IsLessThanOrEqual(T a, T b) {
     89    return a <= b;
     90  }
     91 
     92 public:
     93  using IntegralType = std::underlying_type_t<E>;
     94  static constexpr auto kMinLegalIntegral = static_cast<IntegralType>(MinLegal);
     95  static constexpr auto kHighBoundIntegral =
     96      static_cast<IntegralType>(HighBound);
     97 
     98  static bool IsLegalValue(const IntegralType e) {
     99    return IsLessThanOrEqual(kMinLegalIntegral, e) && e < kHighBoundIntegral;
    100  }
    101 };
    102 
    103 template <typename E, E MinLegal, E MaxLegal>
    104 class ContiguousEnumValidatorInclusive {
    105  // Silence overzealous -Wtype-limits bug in GCC fixed in GCC 4.8:
    106  // "comparison of unsigned expression >= 0 is always true"
    107  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
    108  template <typename T>
    109  static bool IsLessThanOrEqual(T a, T b) {
    110    return a <= b;
    111  }
    112 
    113 public:
    114  using IntegralType = std::underlying_type_t<E>;
    115  static constexpr auto kMinLegalIntegral = static_cast<IntegralType>(MinLegal);
    116  static constexpr auto kMaxLegalIntegral = static_cast<IntegralType>(MaxLegal);
    117 
    118  static bool IsLegalValue(const IntegralType e) {
    119    return IsLessThanOrEqual(kMinLegalIntegral, e) && e <= kMaxLegalIntegral;
    120  }
    121 };
    122 
    123 template <typename E, E AllBits>
    124 struct BitFlagsEnumValidator {
    125  static bool IsLegalValue(const std::underlying_type_t<E> e) {
    126    return (e & static_cast<std::underlying_type_t<E>>(AllBits)) == e;
    127  }
    128 };
    129 
    130 /**
    131 * Specialization of EnumSerializer for enums with contiguous enum values.
    132 *
    133 * Provide two values: MinLegal, HighBound. An enum value x will be
    134 * considered legal if MinLegal <= x < HighBound.
    135 *
    136 * For example, following is definition of serializer for enum type FOO.
    137 * \code
    138 * enum FOO { FOO_FIRST, FOO_SECOND, FOO_LAST, NUM_FOO };
    139 *
    140 * template <>
    141 * struct ParamTraits<FOO>:
    142 *     public ContiguousEnumSerializer<FOO, FOO_FIRST, NUM_FOO> {};
    143 * \endcode
    144 * FOO_FIRST, FOO_SECOND, and FOO_LAST are valid value.
    145 */
    146 template <typename E, E MinLegal, E HighBound>
    147 struct ContiguousEnumSerializer
    148    : EnumSerializer<E, ContiguousEnumValidator<E, MinLegal, HighBound>> {};
    149 
    150 /**
    151 * This is similar to ContiguousEnumSerializer, but the last template
    152 * parameter is expected to be the highest legal value, rather than a
    153 * sentinel value. This is intended to support enumerations that don't
    154 * have sentinel values.
    155 */
    156 template <typename E, E MinLegal, E MaxLegal>
    157 struct ContiguousEnumSerializerInclusive
    158    : EnumSerializer<E,
    159                     ContiguousEnumValidatorInclusive<E, MinLegal, MaxLegal>> {
    160 };
    161 
    162 /**
    163 * Specialization of EnumSerializer for enums representing bit flags.
    164 *
    165 * Provide one value: AllBits. An enum value x will be
    166 * considered legal if (x & AllBits) == x;
    167 *
    168 * Example:
    169 * \code
    170 * enum FOO {
    171 *   FOO_FIRST =  1 << 0,
    172 *   FOO_SECOND = 1 << 1,
    173 *   FOO_LAST =   1 << 2,
    174 *   ALL_BITS =   (1 << 3) - 1
    175 * };
    176 *
    177 * template <>
    178 * struct ParamTraits<FOO>:
    179 *     public BitFlagsEnumSerializer<FOO, FOO::ALL_BITS> {};
    180 * \endcode
    181 */
    182 template <typename E, E AllBits>
    183 struct BitFlagsEnumSerializer
    184    : EnumSerializer<E, BitFlagsEnumValidator<E, AllBits>> {};
    185 
    186 } /* namespace IPC */
    187 
    188 #endif /* __IPC_GLUE_ENUMSERIALIZER_H__ */