tor-browser

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

ICUError.h (4006B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef intl_components_ICUError_h
      6 #define intl_components_ICUError_h
      7 
      8 #include "mozilla/Attributes.h"
      9 #include "mozilla/Result.h"
     10 
     11 #include <cstdint>
     12 #include <type_traits>
     13 
     14 namespace mozilla::intl {
     15 
     16 /**
     17 * General purpose error type for operations that can result in an ICU error.
     18 */
     19 enum class ICUError : uint8_t {
     20  // Since we claim UnusedZero<ICUError>::value and
     21  // HasFreeLSB<ICUError>::value == true below, we must only use positive,
     22  // even enum values.
     23 
     24  OutOfMemory = 2,
     25  InternalError = 4,
     26  OverflowError = 6,
     27 };
     28 
     29 /**
     30 * Error type when a method call can only result in an internal ICU error.
     31 */
     32 struct InternalError {
     33  // Since we claim UnusedZero<InternalError>::value and
     34  // HasFreeLSB<InternalError>::value == true below, we must only use positive,
     35  // even enum values.
     36  enum class ErrorKind : uint8_t { Unspecified = 2 };
     37 
     38  const ErrorKind kind = ErrorKind::Unspecified;
     39 
     40  constexpr InternalError() = default;
     41 
     42 private:
     43  friend struct mozilla::detail::UnusedZero<InternalError>;
     44 
     45  constexpr MOZ_IMPLICIT InternalError(ErrorKind aKind) : kind(aKind) {}
     46 };
     47 
     48 }  // namespace mozilla::intl
     49 
     50 namespace mozilla::detail {
     51 
     52 // Provide specializations for UnusedZero and HasFreeLSB to enable more
     53 // efficient packing for mozilla::Result. This also avoids having to include
     54 // the ResultVariant.h header.
     55 //
     56 // UnusedZero specialization:
     57 //
     58 // The UnusedZero specialization makes it possible to use CompactPair as the
     59 // underlying storage type for Result. For this optimization to work, it is
     60 // necessary that a distinct null-value is present for the error type. The
     61 // null-value represents the success case and must be different from all actual
     62 // error values.
     63 // This optimization can be easily enabled when the error type is a scoped enum.
     64 // No enum value must use zero as its value and UnusedZero must be specialized
     65 // through the helper struct UnusedZeroEnum.
     66 // For non-enum error types, a more complicated setup is necessary. The
     67 // UnusedZero specialization must implement all necessary interface methods
     68 // (i.e. `Inspect`, `Unwrap`, and `Store`) as well as all necessary constants
     69 // and types (i.e. `StorageType`, `value`, and `nullValue`).
     70 //
     71 // HasFreeLSB specialization:
     72 //
     73 // When the value and the error type are both providing specializations for
     74 // HasFreeLSB, Result uses an optimization to store both types within a single
     75 // storage location. This optimization uses the least significant bit as a tag
     76 // bit to mark the error case. And because the least significant bit is used for
     77 // tagging, it can't be used by the error type. That means for example when the
     78 // error type is an enum, all enum values must be even, because odd integer
     79 // values have the least significant bit set.
     80 // The actual HasFreeLSB specialization just needs to define `value` as a static
     81 // constant with the value `true`.
     82 
     83 template <>
     84 struct UnusedZero<mozilla::intl::ICUError>
     85    : UnusedZeroEnum<mozilla::intl::ICUError> {};
     86 
     87 template <>
     88 struct UnusedZero<mozilla::intl::InternalError> {
     89  using Error = mozilla::intl::InternalError;
     90  using StorageType = std::underlying_type_t<Error::ErrorKind>;
     91 
     92  static constexpr bool value = true;
     93  static constexpr StorageType nullValue = 0;
     94 
     95  static constexpr Error Inspect(const StorageType& aValue) {
     96    return static_cast<Error::ErrorKind>(aValue);
     97  }
     98  static constexpr Error Unwrap(StorageType aValue) {
     99    return static_cast<Error::ErrorKind>(aValue);
    100  }
    101  static constexpr StorageType Store(Error aValue) {
    102    return static_cast<StorageType>(aValue.kind);
    103  }
    104 };
    105 
    106 template <>
    107 struct HasFreeLSB<mozilla::intl::ICUError> {
    108  static constexpr bool value = true;
    109 };
    110 
    111 template <>
    112 struct HasFreeLSB<mozilla::intl::InternalError> {
    113  static constexpr bool value = true;
    114 };
    115 
    116 }  // namespace mozilla::detail
    117 
    118 #endif