/* 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 #include namespace mozilla { namespace dom { namespace indexedDB { // IDBSpecialValue represents two special return values, distinct from any other // value, used in several places in the IndexedDB spec. enum class IDBSpecialValue { Failure, Invalid, }; namespace detail { template struct OkType final { T mValue; }; template <> struct OkType final {}; template using SpecialConstant = std::integral_constant; using FailureType = detail::SpecialConstant; using InvalidType = detail::SpecialConstant; struct ExceptionType final {}; struct VoidType final {}; } // namespace detail namespace { template constexpr inline detail::OkType> Ok(T&& aValue) { return {std::forward(aValue)}; } constexpr inline detail::OkType Ok() { return {}; } constexpr const detail::FailureType Failure; constexpr const detail::InvalidType Invalid; constexpr const detail::ExceptionType Exception; } // namespace namespace detail { template struct IsSortedSet; template struct IsSortedSet : std::integral_constant::value && IsSortedSet::value> {}; template struct IsSortedSet : std::integral_constant {}; template struct IsSortedSet : std::true_type {}; template <> struct IsSortedSet<> : std::true_type {}; // IDBResultBase contains the bulk of the implementation of IDBResult, namely // functionality that's applicable to all values of T. template class IDBResultBase { // This assertion ensures that permutations of the set of possible special // values don't create distinct types. static_assert(detail::IsSortedSet::value, "special value list must be sorted and unique"); template friend class IDBResultBase; protected: using ValueType = detail::OkType; public: // Construct a normal result. Use the Ok function to create an object of type // ValueType. MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {} MOZ_IMPLICIT IDBResultBase(detail::ExceptionType) : mVariant(detail::ExceptionType{}) {} template MOZ_IMPLICIT IDBResultBase(detail::SpecialConstant) : mVariant(detail::SpecialConstant{}) {} using VariantType = Variant...>; struct Matcher { template VariantType match(const V& aVariant) const { return VariantType{aVariant}; }; }; // Construct an IDBResult from another IDBResult whose set of possible special // values is a subset of this one's. template MOZ_IMPLICIT IDBResultBase(const IDBResultBase& aOther) : mVariant(aOther.mVariant.match(Matcher())) {} // Test whether the result is a normal return value. The choice of the first // parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting // readability and uniformity with other functions in the overload set. bool Is(detail::OkType (*)(), const ErrorResult& aRv) const { AssertConsistency(aRv); return mVariant.template is(); } bool Is(detail::ExceptionType, const ErrorResult& aRv) const { AssertConsistency(aRv); return mVariant.template is(); } template bool Is(detail::SpecialConstant, const ErrorResult& aRv) const { AssertConsistency(aRv); return mVariant.template is>(); } protected: void AssertConsistency(const ErrorResult& aRv) const { MOZ_ASSERT(aRv.Failed() == mVariant.template is()); } 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 class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase { public: using IDBResult::IDBResultBase::IDBResultBase; // Get a reference to the regular return value, asserting that this object // is indeed a regular return value. T& Unwrap(const ErrorResult& aRv) { return const_cast(static_cast(this)->Unwrap(aRv)); } const T& Unwrap(const ErrorResult& aRv) const { this->AssertConsistency(aRv); return this->mVariant.template as().mValue; } }; template class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase { public: using IDBResult::IDBResultBase::IDBResultBase; }; } // namespace indexedDB } // namespace dom } // namespace mozilla #endif // mozilla_dom_indexeddb_idbresult_h__