Source code

Revision control

Other Tools

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 <mozilla/ErrorResult.h>
9
#include <mozilla/Variant.h>
10
11
#include <type_traits>
12
#include <utility>
13
14
namespace mozilla {
15
namespace dom {
16
namespace indexedDB {
17
18
// IDBSpecialValue represents two special return values, distinct from any other
19
// value, used in several places in the IndexedDB spec.
20
enum class IDBSpecialValue {
21
Failure,
22
Invalid,
23
};
24
25
namespace detail {
26
template <typename T>
27
struct OkType final {
28
T mValue;
29
};
30
31
template <>
32
struct OkType<void> final {};
33
34
template <IDBSpecialValue Value>
35
using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
36
using FailureType = detail::SpecialConstant<IDBSpecialValue::Failure>;
37
using InvalidType = detail::SpecialConstant<IDBSpecialValue::Invalid>;
38
struct ExceptionType final {};
39
struct VoidType final {};
40
} // namespace detail
41
42
namespace {
43
template <typename T>
44
constexpr inline detail::OkType<std::remove_reference_t<T>> Ok(T&& aValue) {
45
return {std::forward<T>(aValue)};
46
}
47
48
constexpr inline detail::OkType<void> Ok() { return {}; }
49
50
constexpr const detail::FailureType Failure;
51
constexpr const detail::InvalidType Invalid;
52
constexpr const detail::ExceptionType Exception;
53
} // namespace
54
55
namespace detail {
56
template <IDBSpecialValue... Elements>
57
struct IsSortedSet;
58
59
template <IDBSpecialValue First, IDBSpecialValue Second,
60
IDBSpecialValue... Rest>
61
struct IsSortedSet<First, Second, Rest...>
62
: std::integral_constant<bool, IsSortedSet<First, Second>::value &&
63
IsSortedSet<Second, Rest...>::value> {};
64
65
template <IDBSpecialValue First, IDBSpecialValue Second>
66
struct IsSortedSet<First, Second>
67
: std::integral_constant<bool, (First < Second)> {};
68
69
template <IDBSpecialValue First>
70
struct IsSortedSet<First> : std::true_type {};
71
72
template <>
73
struct IsSortedSet<> : std::true_type {};
74
75
// IDBResultBase contains the bulk of the implementation of IDBResult, namely
76
// functionality that's applicable to all values of T.
77
template <typename T, IDBSpecialValue... S>
78
class IDBResultBase {
79
// This assertion ensures that permutations of the set of possible special
80
// values don't create distinct types.
81
static_assert(detail::IsSortedSet<S...>::value,
82
"special value list must be sorted and unique");
83
84
template <typename R, IDBSpecialValue... U>
85
friend class IDBResultBase;
86
87
protected:
88
using ValueType = detail::OkType<T>;
89
90
public:
91
// Construct a normal result. Use the Ok function to create an object of type
92
// ValueType.
93
MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {}
94
95
MOZ_IMPLICIT IDBResultBase(detail::ExceptionType)
96
: mVariant(detail::ExceptionType{}) {}
97
98
template <IDBSpecialValue Special>
99
MOZ_IMPLICIT IDBResultBase(detail::SpecialConstant<Special>)
100
: mVariant(detail::SpecialConstant<Special>{}) {}
101
102
// Construct an IDBResult from another IDBResult whose set of possible special
103
// values is a subset of this one's.
104
template <IDBSpecialValue... U>
105
MOZ_IMPLICIT IDBResultBase(const IDBResultBase<T, U...>& aOther)
106
: mVariant(aOther.mVariant.match(
107
[](auto& aVariant) { return VariantType{aVariant}; })) {}
108
109
// Test whether the result is a normal return value. The choice of the first
110
// parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting
111
// readability and uniformity with other functions in the overload set.
112
bool Is(detail::OkType<void> (*)(), const ErrorResult& aRv) const {
113
AssertConsistency(aRv);
114
return mVariant.template is<ValueType>();
115
}
116
117
bool Is(detail::ExceptionType, const ErrorResult& aRv) const {
118
AssertConsistency(aRv);
119
return mVariant.template is<detail::ExceptionType>();
120
}
121
122
template <IDBSpecialValue Special>
123
bool Is(detail::SpecialConstant<Special>, const ErrorResult& aRv) const {
124
AssertConsistency(aRv);
125
return mVariant.template is<detail::SpecialConstant<Special>>();
126
}
127
128
protected:
129
void AssertConsistency(const ErrorResult& aRv) const {
130
MOZ_ASSERT(aRv.Failed() == mVariant.template is<detail::ExceptionType>());
131
}
132
133
using VariantType =
134
Variant<ValueType, detail::ExceptionType, detail::SpecialConstant<S>...>;
135
136
VariantType mVariant;
137
};
138
} // namespace detail
139
140
// Represents a return value of an IndexedDB algorithm. T is the type of the
141
// regular return value, while S is a list of special values that can be
142
// returned by the particular algorithm.
143
template <typename T, IDBSpecialValue... S>
144
class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase<T, S...> {
145
public:
146
using IDBResult::IDBResultBase::IDBResultBase;
147
148
// Get a reference to the regular return value, asserting that this object
149
// is indeed a regular return value.
150
T& Unwrap(const ErrorResult& aRv) {
151
return const_cast<T&>(static_cast<const IDBResult*>(this)->Unwrap(aRv));
152
}
153
154
const T& Unwrap(const ErrorResult& aRv) const {
155
this->AssertConsistency(aRv);
156
return this->mVariant.template as<typename IDBResult::ValueType>().mValue;
157
}
158
};
159
160
template <IDBSpecialValue... S>
161
class MOZ_MUST_USE_TYPE IDBResult<void, S...>
162
: public detail::IDBResultBase<void, S...> {
163
public:
164
using IDBResult::IDBResultBase::IDBResultBase;
165
};
166
167
} // namespace indexedDB
168
} // namespace dom
169
} // namespace mozilla
170
171
#endif // mozilla_dom_indexeddb_idbresult_h__