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/. */
6 
7 #ifndef DOM_QUOTA_QMRESULTINLINES_H_
8 #define DOM_QUOTA_QMRESULTINLINES_H_
9 
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"
16 
17 #ifdef QM_ERROR_STACKS_ENABLED
18 #  include "mozilla/ResultVariant.h"
19 #endif
20 
21 namespace mozilla {
22 
23 #ifdef QM_ERROR_STACKS_ENABLED
24 // Allow QMResult errors to use existing stack id and to increase the frame id
25 // during error propagation.
26 template <>
27 class [[nodiscard]] GenericErrorResult<QMResult> {
28   QMResult mErrorValue;
29 
30   template <typename V, typename E2>
31   friend class Result;
32 
33  public:
GenericErrorResult(const QMResult & aErrorValue)34   explicit GenericErrorResult(const QMResult& aErrorValue)
35       : mErrorValue(aErrorValue) {
36     MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
37   }
38 
GenericErrorResult(QMResult && aErrorValue)39   explicit GenericErrorResult(QMResult&& aErrorValue)
40       : mErrorValue(std::move(aErrorValue)) {
41     MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult()));
42   }
43 
GenericErrorResult(const QMResult & aErrorValue,const ErrorPropagationTag &)44   explicit GenericErrorResult(const QMResult& aErrorValue,
45                               const ErrorPropagationTag&)
46       : GenericErrorResult(aErrorValue.Propagate()) {}
47 
GenericErrorResult(QMResult && aErrorValue,const ErrorPropagationTag &)48   explicit GenericErrorResult(QMResult&& aErrorValue,
49                               const ErrorPropagationTag&)
50       : GenericErrorResult(aErrorValue.Propagate()) {}
51 
QMResult()52   operator QMResult() const { return mErrorValue; }
53 
nsresult()54   operator nsresult() const { return mErrorValue.NSResult(); }
55 };
56 
57 template <>
58 struct ResultTypeTraits<QMResult> {
59   static QMResult From(nsresult aValue) { return ToQMResult(aValue); }
60 
61   static QMResult From(const QMResult& aValue) { return aValue; }
62 
63   static QMResult From(QMResult&& aValue) { return std::move(aValue); }
64 };
65 
66 template <typename E>
67 inline Result<Ok, E> ToResult(const QMResult& aValue) {
68   if (NS_FAILED(aValue.NSResult())) {
69     return Err(ResultTypeTraits<E>::From(aValue));
70   }
71   return Ok();
72 }
73 
74 template <typename E>
75 inline Result<Ok, E> ToResult(QMResult&& aValue) {
76   if (NS_FAILED(aValue.NSResult())) {
77     return Err(ResultTypeTraits<E>::From(aValue));
78   }
79   return Ok();
80 }
81 #endif
82 
83 template <typename E = nsresult, typename V, typename E2>
84 inline Result<V, E> ToResultTransform(Result<V, E2>&& aValue) {
85   return std::forward<Result<V, E2>>(aValue).mapErr(
86       [](auto&& err) { return ResultTypeTraits<E>::From(err); });
87 }
88 
89 // TODO: Maybe move this to mfbt/ResultExtensions.h
90 template <typename R, typename Func, typename... Args>
91 Result<R, nsresult> ToResultGet(const Func& aFunc, Args&&... aArgs) {
92   nsresult rv;
93   R res = aFunc(std::forward<Args>(aArgs)..., &rv);
94   if (NS_FAILED(rv)) {
95     return Err(rv);
96   }
97   return res;
98 }
99 
100 }  // namespace mozilla
101 
102 // TODO: Maybe move this to mfbt/ResultExtensions.h
103 #define MOZ_TO_RESULT(expr) ToResult(expr)
104 
105 #define QM_TO_RESULT(expr) ToResult<QMResult>(expr)
106 
107 #define QM_TO_RESULT_TRANSFORM(value) ToResultTransform<QMResult>(value)
108 
109 #define MOZ_TO_RESULT_GET_TYPED(resultType, ...) \
110   ::mozilla::ToResultGet<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__)
111 
112 #define MOZ_TO_RESULT_INVOKE_TYPED(resultType, ...) \
113   ::mozilla::ToResultInvoke<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__)
114 
115 #define QM_TO_RESULT_INVOKE_MEMBER(obj, methodname, ...)                 \
116   ::mozilla::ToResultInvokeMember<QMResult>(                             \
117       (obj), &::mozilla::detail::DerefedType<decltype(obj)>::methodname, \
118       ##__VA_ARGS__)
119 
120 #define QM_TO_RESULT_INVOKE_MEMBER_TYPED(resultType, obj, methodname, ...) \
121   (::mozilla::ToResultInvoke<resultType, QMResult>(                        \
122       ::std::mem_fn(                                                       \
123           &::mozilla::detail::DerefedType<decltype(obj)>::methodname),     \
124       (obj), ##__VA_ARGS__))
125 
126 #endif
127