ResultExtensions.h (5012B)
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 "mozilla/Result.h" 11 #include "mozilla/ResultExtensions.h" 12 #include "mozilla/dom/QMResult.h" 13 #include "mozilla/dom/quota/Config.h" 14 #include "mozilla/dom/quota/RemoveParen.h" 15 #include "nsError.h" 16 17 #ifdef QM_ERROR_STACKS_ENABLED 18 # include "mozilla/ResultVariant.h" 19 #endif 20 21 namespace mozilla { 22 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; 28 29 template <typename V, typename E2> 30 friend class Result; 31 32 public: 33 explicit GenericErrorResult(bool aErrorValue) : mErrorValue(aErrorValue) { 34 MOZ_ASSERT(!aErrorValue); 35 } 36 37 GenericErrorResult(bool aErrorValue, const ErrorPropagationTag&) 38 : GenericErrorResult(aErrorValue) {} 39 40 MOZ_IMPLICIT operator bool() const { return mErrorValue; } 41 }; 42 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(); 48 } 49 return Err(ResultTypeTraits<E>::From(NS_ERROR_FAILURE)); 50 } 51 52 constexpr nsresult ToNSResult(nsresult aError) { return aError; } 53 54 #ifdef QM_ERROR_STACKS_ENABLED 55 56 inline nsresult ToNSResult(const QMResult& aError) { return aError.NSResult(); } 57 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; 63 64 template <typename V, typename E2> 65 friend class Result; 66 67 public: 68 explicit GenericErrorResult(const QMResult& aErrorValue) 69 : mErrorValue(aErrorValue) { 70 MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult())); 71 } 72 73 explicit GenericErrorResult(QMResult&& aErrorValue) 74 : mErrorValue(std::move(aErrorValue)) { 75 MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult())); 76 } 77 78 explicit GenericErrorResult(const QMResult& aErrorValue, 79 const ErrorPropagationTag&) 80 : GenericErrorResult(aErrorValue.Propagate()) {} 81 82 explicit GenericErrorResult(QMResult&& aErrorValue, 83 const ErrorPropagationTag&) 84 : GenericErrorResult(aErrorValue.Propagate()) {} 85 86 operator QMResult() const { return mErrorValue; } 87 88 operator nsresult() const { return mErrorValue.NSResult(); } 89 }; 90 91 template <> 92 struct ResultTypeTraits<QMResult> { 93 static QMResult From(nsresult aValue) { return ToQMResult(aValue); } 94 95 static QMResult From(const QMResult& aValue) { return aValue; } 96 97 static QMResult From(QMResult&& aValue) { return std::move(aValue); } 98 }; 99 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)); 104 } 105 return Ok(); 106 } 107 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)); 112 } 113 return Ok(); 114 } 115 #endif 116 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); }); 121 } 122 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); 130 } 131 return res; 132 } 133 134 } // namespace mozilla 135 136 // TODO: Maybe move this to mfbt/ResultExtensions.h 137 #define MOZ_TO_RESULT(expr) ToResult(expr) 138 139 #define QM_TO_RESULT(expr) ToResult<QMResult>(expr) 140 141 #define QM_TO_RESULT_TRANSFORM(value) ToResultTransform<QMResult>(value) 142 143 #define MOZ_TO_RESULT_GET_TYPED(resultType, ...) \ 144 ::mozilla::ToResultGet<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__) 145 146 #define MOZ_TO_RESULT_INVOKE_TYPED(resultType, ...) \ 147 ::mozilla::ToResultInvoke<MOZ_REMOVE_PAREN(resultType)>(__VA_ARGS__) 148 149 #define QM_TO_RESULT_INVOKE_MEMBER(obj, methodname, ...) \ 150 ::mozilla::ToResultInvokeMember<QMResult>( \ 151 (obj), &::mozilla::detail::DerefedType<decltype(obj)>::methodname, \ 152 ##__VA_ARGS__) 153 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__)) 159 160 #endif