/* 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 mozilla_dom_indexeddb_idbresult_h_ #define mozilla_dom_indexeddb_idbresult_h_ #include #include #include "mozilla/ErrorResult.h" #include "mozilla/ResultVariant.h" #include "mozilla/Variant.h" namespace mozilla::dom::indexedDB { // IDBSpecialValue represents three special return values, distinct from any // other value, used in several places in the IndexedDB spec. enum class IDBSpecialValue { Failure, InvalidType, InvalidValue }; namespace detail { template using SpecialConstant = std::integral_constant; using FailureType = SpecialConstant; using InvalidTypeType = SpecialConstant; using InvalidValueType = SpecialConstant; struct ExceptionType final {}; } // namespace detail // Put these in a subnamespace to avoid conflicts from the combination of 1. // using namespace mozilla::dom::indexedDB; in cpp files, 2. the unified build // and 3. mozilla::dom::Exception namespace SpecialValues { constexpr const detail::FailureType Failure; constexpr const detail::InvalidTypeType InvalidType; constexpr const detail::InvalidValueType InvalidValue; constexpr const detail::ExceptionType Exception; } // namespace SpecialValues namespace detail { template struct IsSortedSet; template struct IsSortedSet : std::conjunction, IsSortedSet> {}; template struct IsSortedSet : std::bool_constant<(First < Second)> {}; template struct IsSortedSet : std::true_type {}; template <> struct IsSortedSet<> : std::true_type {}; template class IDBError { // This assertion ensures that permutations of the set of possible special // values don't create distinct types. static_assert(IsSortedSet::value, "special value list must be sorted and unique"); template friend class IDBError; public: MOZ_IMPLICIT IDBError(nsresult aRv) : mVariant(ErrorResult{aRv}) {} IDBError(ExceptionType, ErrorResult&& aErrorResult) : mVariant(std::move(aErrorResult)) {} template MOZ_IMPLICIT IDBError(SpecialConstant) : mVariant(SpecialConstant{}) {} IDBError(IDBError&&) = default; IDBError& operator=(IDBError&&) = default; // Construct an IDBResult from another IDBResult whose set of possible special // values is a subset of this one's. template MOZ_IMPLICIT IDBError(IDBError&& aOther) : mVariant(aOther.mVariant.match( [](auto& aVariant) { return VariantType{std::move(aVariant)}; })) {} bool Is(ExceptionType) const { return mVariant.template is(); } template bool Is(SpecialConstant) const { return mVariant.template is>(); } ErrorResult& AsException() { return mVariant.template as(); } template ErrorResult ExtractErrorResult(SpecialValueMappers aSpecialValueMappers) { return mVariant.match( [](ErrorResult& aException) { return std::move(aException); }, [aSpecialValueMappers](const SpecialConstant& aSpecialValue) { return ErrorResult{aSpecialValueMappers(aSpecialValue)}; }...); } protected: using VariantType = Variant...>; VariantType mVariant; }; } // namespace detail // Represents a return value of an IndexedDB algorithm. T is the type of the // regular return value, while S is a list of special values that can be // returned by the particular algorithm. template using IDBResult = Result>; template inline constexpr auto InvalidMapsTo = [](auto) { return E; }; inline detail::IDBError<> IDBException(nsresult aRv) { return {SpecialValues::Exception, ErrorResult{aRv}}; } template detail::IDBError IDBError(detail::SpecialConstant aResult) { return {aResult}; } } // namespace mozilla::dom::indexedDB #endif // mozilla_dom_indexeddb_idbresult_h_