|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#ifndef mozilla_dom_indexeddb_idbresult_h__
|
|
Packit |
f0b94e |
#define mozilla_dom_indexeddb_idbresult_h__
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include <mozilla/ErrorResult.h>
|
|
Packit |
f0b94e |
#include <mozilla/Variant.h>
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include <type_traits>
|
|
Packit |
f0b94e |
#include <utility>
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
namespace dom {
|
|
Packit |
f0b94e |
namespace indexedDB {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// IDBSpecialValue represents two special return values, distinct from any other
|
|
Packit |
f0b94e |
// value, used in several places in the IndexedDB spec.
|
|
Packit |
f0b94e |
enum class IDBSpecialValue {
|
|
Packit |
f0b94e |
Failure,
|
|
Packit |
f0b94e |
Invalid,
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace detail {
|
|
Packit |
f0b94e |
template <typename T>
|
|
Packit |
f0b94e |
struct OkType final {
|
|
Packit |
f0b94e |
T mValue;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <>
|
|
Packit |
f0b94e |
struct OkType<void> final {};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue Value>
|
|
Packit |
f0b94e |
using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
|
|
Packit |
f0b94e |
using FailureType = detail::SpecialConstant<IDBSpecialValue::Failure>;
|
|
Packit |
f0b94e |
using InvalidType = detail::SpecialConstant<IDBSpecialValue::Invalid>;
|
|
Packit |
f0b94e |
struct ExceptionType final {};
|
|
Packit |
f0b94e |
struct VoidType final {};
|
|
Packit |
f0b94e |
} // namespace detail
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace {
|
|
Packit |
f0b94e |
template <typename T>
|
|
Packit |
f0b94e |
constexpr inline detail::OkType<std::remove_reference_t<T>> Ok(T&& aValue) {
|
|
Packit |
f0b94e |
return {std::forward<T>(aValue)};
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
constexpr inline detail::OkType<void> Ok() { return {}; }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
constexpr const detail::FailureType Failure;
|
|
Packit |
f0b94e |
constexpr const detail::InvalidType Invalid;
|
|
Packit |
f0b94e |
constexpr const detail::ExceptionType Exception;
|
|
Packit |
f0b94e |
} // namespace
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace detail {
|
|
Packit |
f0b94e |
template <IDBSpecialValue... Elements>
|
|
Packit |
f0b94e |
struct IsSortedSet;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template
|
|
Packit |
f0b94e |
IDBSpecialValue... Rest>
|
|
Packit |
f0b94e |
struct IsSortedSet<First, Second, Rest...>
|
|
Packit |
f0b94e |
: std::integral_constant<bool, IsSortedSet<First, Second>::value &&
|
|
Packit |
f0b94e |
IsSortedSet<Second, Rest...>::value> {};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue First, IDBSpecialValue Second>
|
|
Packit |
f0b94e |
struct IsSortedSet<First, Second>
|
|
Packit |
f0b94e |
: std::integral_constant<bool, (First < Second)> {};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue First>
|
|
Packit |
f0b94e |
struct IsSortedSet<First> : std::true_type {};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <>
|
|
Packit |
f0b94e |
struct IsSortedSet<> : std::true_type {};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// IDBResultBase contains the bulk of the implementation of IDBResult, namely
|
|
Packit |
f0b94e |
// functionality that's applicable to all values of T.
|
|
Packit |
f0b94e |
template <typename T, IDBSpecialValue... S>
|
|
Packit |
f0b94e |
class IDBResultBase {
|
|
Packit |
f0b94e |
// This assertion ensures that permutations of the set of possible special
|
|
Packit |
f0b94e |
// values don't create distinct types.
|
|
Packit |
f0b94e |
static_assert(detail::IsSortedSet<S...>::value,
|
|
Packit |
f0b94e |
"special value list must be sorted and unique");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <typename R, IDBSpecialValue... U>
|
|
Packit |
f0b94e |
friend class IDBResultBase;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
protected:
|
|
Packit |
f0b94e |
using ValueType = detail::OkType<T>;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
// Construct a normal result. Use the Ok function to create an object of type
|
|
Packit |
f0b94e |
// ValueType.
|
|
Packit |
f0b94e |
MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
MOZ_IMPLICIT IDBResultBase(detail::ExceptionType)
|
|
Packit |
f0b94e |
: mVariant(detail::ExceptionType{}) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue Special>
|
|
Packit |
f0b94e |
MOZ_IMPLICIT IDBResultBase(detail::SpecialConstant<Special>)
|
|
Packit |
f0b94e |
: mVariant(detail::SpecialConstant<Special>{}) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
using VariantType =
|
|
Packit |
f0b94e |
Variant<ValueType, detail::ExceptionType, detail::SpecialConstant<S>...>;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
struct Matcher {
|
|
Packit |
f0b94e |
template <typename V>
|
|
Packit |
f0b94e |
VariantType match(const V& aVariant) const {
|
|
Packit |
f0b94e |
return VariantType{aVariant};
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Construct an IDBResult from another IDBResult whose set of possible special
|
|
Packit |
f0b94e |
// values is a subset of this one's.
|
|
Packit |
f0b94e |
template <IDBSpecialValue... U>
|
|
Packit |
f0b94e |
MOZ_IMPLICIT IDBResultBase(const IDBResultBase<T, U...>& aOther)
|
|
Packit |
f0b94e |
: mVariant(aOther.mVariant.match(Matcher())) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Test whether the result is a normal return value. The choice of the first
|
|
Packit |
f0b94e |
// parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting
|
|
Packit |
f0b94e |
// readability and uniformity with other functions in the overload set.
|
|
Packit |
f0b94e |
bool Is(detail::OkType<void> (*)(), const ErrorResult& aRv) const {
|
|
Packit |
f0b94e |
AssertConsistency(aRv);
|
|
Packit |
f0b94e |
return mVariant.template is<ValueType>();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
bool Is(detail::ExceptionType, const ErrorResult& aRv) const {
|
|
Packit |
f0b94e |
AssertConsistency(aRv);
|
|
Packit |
f0b94e |
return mVariant.template is<detail::ExceptionType>();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue Special>
|
|
Packit |
f0b94e |
bool Is(detail::SpecialConstant<Special>, const ErrorResult& aRv) const {
|
|
Packit |
f0b94e |
AssertConsistency(aRv);
|
|
Packit |
f0b94e |
return mVariant.template is<detail::SpecialConstant<Special>>();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
protected:
|
|
Packit |
f0b94e |
void AssertConsistency(const ErrorResult& aRv) const {
|
|
Packit |
f0b94e |
MOZ_ASSERT(aRv.Failed() == mVariant.template is<detail::ExceptionType>());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
VariantType mVariant;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
} // namespace detail
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Represents a return value of an IndexedDB algorithm. T is the type of the
|
|
Packit |
f0b94e |
// regular return value, while S is a list of special values that can be
|
|
Packit |
f0b94e |
// returned by the particular algorithm.
|
|
Packit |
f0b94e |
template <typename T, IDBSpecialValue... S>
|
|
Packit |
f0b94e |
class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase<T, S...> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
using IDBResult::IDBResultBase::IDBResultBase;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Get a reference to the regular return value, asserting that this object
|
|
Packit |
f0b94e |
// is indeed a regular return value.
|
|
Packit |
f0b94e |
T& Unwrap(const ErrorResult& aRv) {
|
|
Packit |
f0b94e |
return const_cast<T&>(static_cast<const IDBResult*>(this)->Unwrap(aRv));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const T& Unwrap(const ErrorResult& aRv) const {
|
|
Packit |
f0b94e |
this->AssertConsistency(aRv);
|
|
Packit |
f0b94e |
return this->mVariant.template as<typename IDBResult::ValueType>().mValue;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
template <IDBSpecialValue... S>
|
|
Packit |
f0b94e |
class MOZ_MUST_USE_TYPE IDBResult<void, S...>
|
|
Packit |
f0b94e |
: public detail::IDBResultBase<void, S...> {
|
|
Packit |
f0b94e |
public:
|
|
Packit |
f0b94e |
using IDBResult::IDBResultBase::IDBResultBase;
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace indexedDB
|
|
Packit |
f0b94e |
} // namespace dom
|
|
Packit |
f0b94e |
} // namespace mozilla
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#endif // mozilla_dom_indexeddb_idbresult_h__
|