tor-browser

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

IDBResult.h (5302B)


      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 mozilla_dom_indexeddb_idbresult_h__
      6 #define mozilla_dom_indexeddb_idbresult_h__
      7 
      8 #include <type_traits>
      9 #include <utility>
     10 
     11 #include "mozilla/ErrorResult.h"
     12 #include "mozilla/ResultVariant.h"
     13 #include "mozilla/Variant.h"
     14 
     15 namespace mozilla::dom::indexedDB {
     16 
     17 // IDBSpecialValue represents two special return values, distinct from any other
     18 // value, used in several places in the IndexedDB spec.
     19 enum class IDBSpecialValue {
     20  Failure,
     21  Invalid,
     22 };
     23 
     24 namespace detail {
     25 
     26 template <IDBSpecialValue Value>
     27 using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
     28 using FailureType = SpecialConstant<IDBSpecialValue::Failure>;
     29 using InvalidType = SpecialConstant<IDBSpecialValue::Invalid>;
     30 struct ExceptionType final {};
     31 }  // namespace detail
     32 
     33 // Put these in a subnamespace to avoid conflicts from the combination of 1.
     34 // using namespace mozilla::dom::indexedDB; in cpp files, 2. the unified build
     35 // and 3. mozilla::dom::Exception
     36 namespace SpecialValues {
     37 constexpr const detail::FailureType Failure;
     38 constexpr const detail::InvalidType Invalid;
     39 constexpr const detail::ExceptionType Exception;
     40 }  // namespace SpecialValues
     41 
     42 namespace detail {
     43 template <IDBSpecialValue... Elements>
     44 struct IsSortedSet;
     45 
     46 template <IDBSpecialValue First, IDBSpecialValue Second,
     47          IDBSpecialValue... Rest>
     48 struct IsSortedSet<First, Second, Rest...>
     49    : std::conjunction<IsSortedSet<First, Second>,
     50                       IsSortedSet<Second, Rest...>> {};
     51 
     52 template <IDBSpecialValue First, IDBSpecialValue Second>
     53 struct IsSortedSet<First, Second> : std::bool_constant<(First < Second)> {};
     54 
     55 template <IDBSpecialValue First>
     56 struct IsSortedSet<First> : std::true_type {};
     57 
     58 template <>
     59 struct IsSortedSet<> : std::true_type {};
     60 
     61 template <IDBSpecialValue... S>
     62 class IDBError {
     63  // This assertion ensures that permutations of the set of possible special
     64  // values don't create distinct types.
     65  static_assert(IsSortedSet<S...>::value,
     66                "special value list must be sorted and unique");
     67 
     68  template <IDBSpecialValue... U>
     69  friend class IDBError;
     70 
     71 public:
     72  MOZ_IMPLICIT IDBError(nsresult aRv) : mVariant(ErrorResult{aRv}) {}
     73 
     74  IDBError(ExceptionType, ErrorResult&& aErrorResult)
     75      : mVariant(std::move(aErrorResult)) {}
     76 
     77  template <IDBSpecialValue Special>
     78  MOZ_IMPLICIT IDBError(SpecialConstant<Special>)
     79      : mVariant(SpecialConstant<Special>{}) {}
     80 
     81  IDBError(IDBError&&) = default;
     82  IDBError& operator=(IDBError&&) = default;
     83 
     84  // Construct an IDBResult from another IDBResult whose set of possible special
     85  // values is a subset of this one's.
     86  template <IDBSpecialValue... U>
     87  MOZ_IMPLICIT IDBError(IDBError<U...>&& aOther)
     88      : mVariant(aOther.mVariant.match(
     89            [](auto& aVariant) { return VariantType{std::move(aVariant)}; })) {}
     90 
     91  bool Is(ExceptionType) const { return mVariant.template is<ErrorResult>(); }
     92 
     93  template <IDBSpecialValue Special>
     94  bool Is(SpecialConstant<Special>) const {
     95    return mVariant.template is<SpecialConstant<Special>>();
     96  }
     97 
     98  ErrorResult& AsException() { return mVariant.template as<ErrorResult>(); }
     99 
    100  template <typename... SpecialValueMappers>
    101  ErrorResult ExtractErrorResult(SpecialValueMappers... aSpecialValueMappers) {
    102 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 8)
    103    return mVariant.match(
    104        [](ErrorResult& aException) { return std::move(aException); },
    105        [aSpecialValueMappers](const SpecialConstant<S>& aSpecialValue) {
    106          return ErrorResult{aSpecialValueMappers(aSpecialValue)};
    107        }...);
    108 #else
    109    // gcc 7 doesn't accept the kind of parameter pack expansion above,
    110    // probably due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
    111    return mVariant.match([aSpecialValueMappers...](auto& aValue) {
    112      if constexpr (std::is_same_v<ErrorResult&, decltype(aValue)>) {
    113        return std::move(aValue);
    114      } else {
    115        return ErrorResult{aSpecialValueMappers(aValue)...};
    116      }
    117    });
    118 #endif
    119  }
    120 
    121  template <typename... SpecialValueMappers>
    122  nsresult ExtractNSResult(SpecialValueMappers... aSpecialValueMappers) {
    123    return mVariant.match(
    124        [](ErrorResult& aException) { return aException.StealNSResult(); },
    125        aSpecialValueMappers...);
    126  }
    127 
    128 protected:
    129  using VariantType = Variant<ErrorResult, SpecialConstant<S>...>;
    130 
    131  VariantType mVariant;
    132 };
    133 }  // namespace detail
    134 
    135 // Represents a return value of an IndexedDB algorithm. T is the type of the
    136 // regular return value, while S is a list of special values that can be
    137 // returned by the particular algorithm.
    138 template <typename T, IDBSpecialValue... S>
    139 using IDBResult = Result<T, detail::IDBError<S...>>;
    140 
    141 template <nsresult E>
    142 nsresult InvalidMapsTo(const indexedDB::detail::InvalidType&) {
    143  return E;
    144 }
    145 
    146 inline detail::IDBError<> IDBException(nsresult aRv) {
    147  return {SpecialValues::Exception, ErrorResult{aRv}};
    148 }
    149 
    150 template <IDBSpecialValue Special>
    151 detail::IDBError<Special> IDBError(detail::SpecialConstant<Special> aResult) {
    152  return {aResult};
    153 }
    154 
    155 }  // namespace mozilla::dom::indexedDB
    156 
    157 #endif  // mozilla_dom_indexeddb_idbresult_h__