@@ -47,16 +47,27 @@ class ResultImplementation<V, E, PackingStrategy::Variant> {
47
47
mozilla::Variant<V, E> mStorage ;
48
48
49
49
public:
50
+ ResultImplementation (ResultImplementation&&) = default ;
51
+ ResultImplementation (const ResultImplementation&) = default ;
52
+ ResultImplementation& operator =(const ResultImplementation&) = default ;
53
+ ResultImplementation& operator =(ResultImplementation&&) = default ;
54
+
55
+ explicit ResultImplementation (V&& aValue)
56
+ : mStorage(std::forward<V>(aValue)) {}
50
57
explicit ResultImplementation (const V& aValue) : mStorage(aValue) {}
51
- explicit ResultImplementation (E aErrorValue) : mStorage(aErrorValue) {}
58
+ explicit ResultImplementation (E aErrorValue)
59
+ : mStorage(std::forward<E>(aErrorValue)) {}
52
60
53
61
bool isOk () const { return mStorage .template is <V>(); }
54
62
55
63
// The callers of these functions will assert isOk() has the proper value, so
56
64
// these functions (in all ResultImplementation specializations) don't need
57
65
// to do so.
58
- V unwrap () const { return mStorage .template as <V>(); }
59
- E unwrapErr () const { return mStorage .template as <E>(); }
66
+ V unwrap () { return std::move (mStorage .template as <V>()); }
67
+ const V& inspect () const { return mStorage .template as <V>(); }
68
+
69
+ E unwrapErr () { return std::move (mStorage .template as <E>()); }
70
+ const E& inspectErr () const { return mStorage .template as <E>(); }
60
71
};
61
72
62
73
/* *
@@ -68,12 +79,18 @@ class ResultImplementation<V, E&, PackingStrategy::Variant> {
68
79
mozilla::Variant<V, E*> mStorage ;
69
80
70
81
public:
82
+ explicit ResultImplementation (V&& aValue)
83
+ : mStorage(std::forward<V>(aValue)) {}
71
84
explicit ResultImplementation (const V& aValue) : mStorage(aValue) {}
72
85
explicit ResultImplementation (E& aErrorValue) : mStorage(&aErrorValue) {}
73
86
74
87
bool isOk () const { return mStorage .template is <V>(); }
75
- V unwrap () const { return mStorage .template as <V>(); }
76
- E& unwrapErr () const { return *mStorage .template as <E*>(); }
88
+
89
+ const V& inspect () const { return mStorage .template as <V>(); }
90
+ V unwrap () { return std::move (mStorage .template as <V>()); }
91
+
92
+ E& unwrapErr () { return *mStorage .template as <E*>(); }
93
+ const E& inspectErr () const { return *mStorage .template as <E*>(); }
77
94
};
78
95
79
96
/* *
@@ -90,8 +107,11 @@ class ResultImplementation<V, E&, PackingStrategy::NullIsOk> {
90
107
91
108
bool isOk () const { return mErrorValue == nullptr ; }
92
109
93
- V unwrap () const { return V (); }
94
- E& unwrapErr () const { return *mErrorValue ; }
110
+ const V& inspect () const = delete;
111
+ V unwrap () { return V (); }
112
+
113
+ const E& inspectErr () const { return *mErrorValue ; }
114
+ E& unwrapErr () { return *mErrorValue ; }
95
115
};
96
116
97
117
/* *
@@ -113,8 +133,11 @@ class ResultImplementation<V, E, PackingStrategy::NullIsOk> {
113
133
114
134
bool isOk () const { return mErrorValue == NullValue; }
115
135
116
- V unwrap () const { return V (); }
117
- E unwrapErr () const { return mErrorValue ; }
136
+ const V& inspect () const = delete;
137
+ V unwrap () { return V (); }
138
+
139
+ const E& inspectErr () const { return mErrorValue ; }
140
+ E unwrapErr () { return std::move (mErrorValue ); }
118
141
};
119
142
120
143
/* *
@@ -139,8 +162,11 @@ class ResultImplementation<V*, E&, PackingStrategy::LowBitTagIsError> {
139
162
140
163
bool isOk () const { return (mBits & 1 ) == 0 ; }
141
164
142
- V* unwrap () const { return reinterpret_cast <V*>(mBits ); }
143
- E& unwrapErr () const { return *reinterpret_cast <E*>(mBits ^ 1 ); }
165
+ V* inspect () const { return reinterpret_cast <V*>(mBits ); }
166
+ V* unwrap () { return inspect (); }
167
+
168
+ E& inspectErr () const { return *reinterpret_cast <E*>(mBits ^ 1 ); }
169
+ E& unwrapErr () { return inspectErr (); }
144
170
};
145
171
146
172
// Return true if any of the struct can fit in a word.
@@ -174,18 +200,21 @@ class ResultImplementation<V, E, PackingStrategy::PackedVariant> {
174
200
175
201
public:
176
202
explicit ResultImplementation (V aValue) {
177
- data.v = aValue;
203
+ data.v = std::move ( aValue) ;
178
204
data.ok = true ;
179
205
}
180
206
explicit ResultImplementation (E aErrorValue) {
181
- data.e = aErrorValue;
207
+ data.e = std::move ( aErrorValue) ;
182
208
data.ok = false ;
183
209
}
184
210
185
211
bool isOk () const { return data.ok ; }
186
212
187
- V unwrap () const { return data.v ; }
188
- E unwrapErr () const { return data.e ; }
213
+ const V& inspect () const { return data.v ; }
214
+ V unwrap () { return std::move (data.v ); }
215
+
216
+ const E& inspectErr () const { return data.e ; }
217
+ E unwrapErr () { return std::move (data.e ); }
189
218
};
190
219
191
220
// To use nullptr as a special value, we need the counter part to exclude zero
@@ -297,15 +326,18 @@ class MOZ_MUST_USE_TYPE Result final {
297
326
Impl mImpl ;
298
327
299
328
public:
300
- /* *
301
- * Create a success result.
302
- */
329
+ /* * Create a success result. */
330
+ MOZ_IMPLICIT Result (V&& aValue) : mImpl(std::forward<V>(aValue)) {
331
+ MOZ_ASSERT (isOk ());
332
+ }
333
+
334
+ /* * Create a success result. */
303
335
MOZ_IMPLICIT Result (const V& aValue) : mImpl(aValue) { MOZ_ASSERT (isOk ()); }
304
336
305
- /* *
306
- * Create an error result.
307
- */
308
- explicit Result (E aErrorValue) : mImpl(aErrorValue) { MOZ_ASSERT ( isErr ()); }
337
+ /* * Create an error result. */
338
+ explicit Result (E aErrorValue) : mImpl(std::forward<E>(aErrorValue)) {
339
+ MOZ_ASSERT ( isErr ());
340
+ }
309
341
310
342
/* *
311
343
* Implementation detail of MOZ_TRY().
@@ -320,32 +352,44 @@ class MOZ_MUST_USE_TYPE Result final {
320
352
}
321
353
322
354
Result (const Result&) = default ;
355
+ Result (Result&&) = default ;
323
356
Result& operator =(const Result&) = default ;
357
+ Result& operator =(Result&&) = default ;
324
358
325
359
/* * True if this Result is a success result. */
326
360
bool isOk () const { return mImpl .isOk (); }
327
361
328
362
/* * True if this Result is an error result. */
329
363
bool isErr () const { return !mImpl .isOk (); }
330
364
331
- /* * Get the success value from this Result, which must be a success result. */
332
- V unwrap () const {
365
+ /* * Take the success value from this Result, which must be a success result.
366
+ */
367
+ V unwrap () {
333
368
MOZ_ASSERT (isOk ());
334
369
return mImpl .unwrap ();
335
370
}
336
371
337
372
/* *
338
- * Get the success value from this Result, which must be a success result.
339
- * If it is an error result, then return the aValue.
373
+ * Take the success value from this Result, which must be a success result.
374
+ * If it is an error result, then return the aValue.
340
375
*/
341
- V unwrapOr (V aValue) const { return isOk () ? mImpl .unwrap () : aValue; }
376
+ V unwrapOr (V aValue) { return isOk () ? mImpl .unwrap () : std::move ( aValue) ; }
342
377
343
- /* * Get the error value from this Result, which must be an error result. */
344
- E unwrapErr () const {
378
+ /* * Take the error value from this Result, which must be an error result. */
379
+ E unwrapErr () {
345
380
MOZ_ASSERT (isErr ());
346
381
return mImpl .unwrapErr ();
347
382
}
348
383
384
+ /* * See the success value from this Result, which must be a success result. */
385
+ const V& inspect () const { return mImpl .inspect (); }
386
+
387
+ /* * See the error value from this Result, which must be an error result. */
388
+ const E& inspectErr () const {
389
+ MOZ_ASSERT (isErr ());
390
+ return mImpl .inspectErr ();
391
+ }
392
+
349
393
/* *
350
394
* Map a function V -> W over this result's success variant. If this result is
351
395
* an error, do not invoke the function and return a copy of the error.
@@ -372,7 +416,7 @@ class MOZ_MUST_USE_TYPE Result final {
372
416
* MOZ_ASSERT(res2.unwrapErr() == 5);
373
417
*/
374
418
template <typename F>
375
- auto map (F f) const -> Result<decltype(f(*((V*)nullptr))), E> {
419
+ auto map (F f) -> Result<decltype(f(*((V*)nullptr))), E> {
376
420
using RetResult = Result<decltype (f (*((V*)nullptr ))), E>;
377
421
return isOk () ? RetResult (f (unwrap ())) : RetResult (unwrapErr ());
378
422
}
@@ -407,7 +451,7 @@ class MOZ_MUST_USE_TYPE Result final {
407
451
*/
408
452
template <typename F, typename = typename EnableIf<detail::IsResult<decltype (
409
453
(*((F*)nullptr ))(*((V*)nullptr )))>::value>::Type>
410
- auto andThen (F f) const -> decltype(f(*((V*)nullptr))) {
454
+ auto andThen (F f) -> decltype(f(*((V*)nullptr))) {
411
455
return isOk () ? f (unwrap ()) : GenericErrorResult<E>(unwrapErr ());
412
456
}
413
457
};
0 commit comments