Bug 1833854 - Part 4: Move all code that deals with maintaining invariants into a...
[gecko.git] / dom / quota / ResultExtensions.h
blobc19bf926612edc9511e552c3331abc5534f54915
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DOM_QUOTA_QMRESULTINLINES_H_
8 #define DOM_QUOTA_QMRESULTINLINES_H_
10 #include "nsError.h"
11 #include "mozilla/Result.h"
12 #include "mozilla/ResultExtensions.h"
13 #include "mozilla/dom/QMResult.h"
14 #include "mozilla/dom/quota/Config.h"
15 #include "mozilla/dom/quota/RemoveParen.h"
17 #ifdef QM_ERROR_STACKS_ENABLED
18 # include "mozilla/ResultVariant.h"
19 #endif
21 namespace mozilla {
23 // Allow bool errors to automatically convert to bool values, so MOZ_TRY/QM_TRY
24 // can be used in bool returning methods with Result<T, bool> results.
25 template <>
26 class [[nodiscard]] GenericErrorResult<bool> {
27 bool mErrorValue;
29 template <typename V, typename E2>
30 friend class Result;
32 public:
33 explicit GenericErrorResult(bool aErrorValue) : mErrorValue(aErrorValue) {
34 MOZ_ASSERT(!aErrorValue);
37 GenericErrorResult(bool aErrorValue, const ErrorPropagationTag&)
38 : GenericErrorResult(aErrorValue) {}
40 MOZ_IMPLICIT operator bool() const { return mErrorValue; }
43 // Allow MOZ_TRY/QM_TRY to handle `bool` values.
44 template <typename E = nsresult>
45 inline Result<Ok, E> ToResult(bool aValue) {
46 if (aValue) {
47 return Ok();
49 return Err(ResultTypeTraits<E>::From(NS_ERROR_FAILURE));
52 constexpr nsresult ToNSResult(nsresult aError) { return aError; }
54 #ifdef QM_ERROR_STACKS_ENABLED
56 inline nsresult ToNSResult(const QMResult& aError) { return aError.NSResult(); }
58 // Allow QMResult errors to use existing stack id and to increase the frame id
59 // during error propagation.
60 template <>
61 class [[nodiscard]] GenericErrorResult<QMResult> {
62 QMResult mErrorValue;
64 template <typename V, typename E2>
65 friend class Result;
67 public:
68 explicit GenericErrorResult(const QMResult& aErrorValue)
69 : mErrorValue(aErrorValue) {
70 MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
73 explicit GenericErrorResult(QMResult&& aErrorValue)
74 : mErrorValue(std::move(aErrorValue)) {
75 MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
78 explicit GenericErrorResult(const QMResult& aErrorValue,
79 const ErrorPropagationTag&)
80 : GenericErrorResult(aErrorValue.Propagate()) {}
82 explicit GenericErrorResult(QMResult&& aErrorValue,
83 const ErrorPropagationTag&)
84 : GenericErrorResult(aErrorValue.Propagate()) {}
86 operator QMResult() const { return mErrorValue; }
88 operator nsresult() const { return mErrorValue.NSResult(); }
91 template <>
92 struct ResultTypeTraits<QMResult> {
93 static QMResult From(nsresult aValue) { return ToQMResult(aValue); }
95 static QMResult From(const QMResult& aValue) { return aValue; }
97 static QMResult From(QMResult&& aValue) { return std::move(aValue); }
100 template <typename E>
101 inline Result<Ok, E> ToResult(const QMResult& aValue) {
102 if (NS_FAILED(aValue.NSResult())) {
103 return Err(ResultTypeTraits<E>::From(aValue));
105 return Ok();
108 template <typename E>
109 inline Result<Ok, E> ToResult(QMResult&& aValue) {
110 if (NS_FAILED(aValue.NSResult())) {
111 return Err(ResultTypeTraits<E>::From(aValue));
113 return Ok();
115 #endif
117 template <typename E = nsresult, typename V, typename E2>
118 inline Result<V, E> ToResultTransform(Result<V, E2>&& aValue) {
119 return std::forward<Result<V, E2>>(aValue).mapErr(
120 [](auto&& err) { return ResultTypeTraits<E>::From(err); });
123 // TODO: Maybe move this to mfbt/ResultExtensions.h
124 template <typename R, typename Func, typename... Args>
125 Result<R, nsresult> ToResultGet(const Func& aFunc, Args&&... aArgs) {
126 nsresult rv;
127 R res = aFunc(std::forward<Args>(aArgs)..., &rv);
128 if (NS_FAILED(rv)) {
129 return Err(rv);
131 return res;
134 } // namespace mozilla
136 // TODO: Maybe move this to mfbt/ResultExtensions.h
137 #define MOZ_TO_RESULT(expr) ToResult(expr)
139 #define QM_TO_RESULT(expr) ToResult<QMResult>(expr)
141 #define QM_TO_RESULT_TRANSFORM(value) ToResultTransform<QMResult>(value)
143 #define MOZ_TO_RESULT_GET_TYPED(resultType, ...) \
144 ::mozilla::ToResultGet<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__)
146 #define MOZ_TO_RESULT_INVOKE_TYPED(resultType, ...) \
147 ::mozilla::ToResultInvoke<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__)
149 #define QM_TO_RESULT_INVOKE_MEMBER(obj, methodname, ...) \
150 ::mozilla::ToResultInvokeMember<QMResult>( \
151 (obj), &::mozilla::detail::DerefedType<decltype(obj)>::methodname, \
152 ##__VA_ARGS__)
154 #define QM_TO_RESULT_INVOKE_MEMBER_TYPED(resultType, obj, methodname, ...) \
155 (::mozilla::ToResultInvoke<resultType, QMResult>( \
156 ::std::mem_fn( \
157 &::mozilla::detail::DerefedType<decltype(obj)>::methodname), \
158 (obj), ##__VA_ARGS__))
160 #endif