/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef DOM_QUOTA_QMRESULTINLINES_H_ #define DOM_QUOTA_QMRESULTINLINES_H_ #include "nsError.h" #include "mozilla/Result.h" #include "mozilla/ResultExtensions.h" #include "mozilla/dom/QMResult.h" #include "mozilla/dom/quota/Config.h" #include "mozilla/dom/quota/RemoveParen.h" #ifdef QM_ERROR_STACKS_ENABLED # include "mozilla/ResultVariant.h" #endif namespace mozilla { // Allow bool errors to automatically convert to bool values, so MOZ_TRY/QM_TRY // can be used in bool returning methods with Result results. template <> class [[nodiscard]] GenericErrorResult { bool mErrorValue; template friend class Result; public: explicit GenericErrorResult(bool aErrorValue) : mErrorValue(aErrorValue) { MOZ_ASSERT(!aErrorValue); } GenericErrorResult(bool aErrorValue, const ErrorPropagationTag&) : GenericErrorResult(aErrorValue) {} MOZ_IMPLICIT operator bool() const { return mErrorValue; } }; // Allow MOZ_TRY/QM_TRY to handle `bool` values. template inline Result ToResult(bool aValue) { if (aValue) { return Ok(); } return Err(ResultTypeTraits::From(NS_ERROR_FAILURE)); } constexpr nsresult ToNSResult(nsresult aError) { return aError; } #ifdef QM_ERROR_STACKS_ENABLED inline nsresult ToNSResult(const QMResult& aError) { return aError.NSResult(); } // Allow QMResult errors to use existing stack id and to increase the frame id // during error propagation. template <> class [[nodiscard]] GenericErrorResult { QMResult mErrorValue; template friend class Result; public: explicit GenericErrorResult(const QMResult& aErrorValue) : mErrorValue(aErrorValue) { MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult())); } explicit GenericErrorResult(QMResult&& aErrorValue) : mErrorValue(std::move(aErrorValue)) { MOZ_ASSERT(NS_FAILED(aErrorValue.NSResult())); } explicit GenericErrorResult(const QMResult& aErrorValue, const ErrorPropagationTag&) : GenericErrorResult(aErrorValue.Propagate()) {} explicit GenericErrorResult(QMResult&& aErrorValue, const ErrorPropagationTag&) : GenericErrorResult(aErrorValue.Propagate()) {} operator QMResult() const { return mErrorValue; } operator nsresult() const { return mErrorValue.NSResult(); } }; template <> struct ResultTypeTraits { static QMResult From(nsresult aValue) { return ToQMResult(aValue); } static QMResult From(const QMResult& aValue) { return aValue; } static QMResult From(QMResult&& aValue) { return std::move(aValue); } }; template inline Result ToResult(const QMResult& aValue) { if (NS_FAILED(aValue.NSResult())) { return Err(ResultTypeTraits::From(aValue)); } return Ok(); } template inline Result ToResult(QMResult&& aValue) { if (NS_FAILED(aValue.NSResult())) { return Err(ResultTypeTraits::From(aValue)); } return Ok(); } #endif template inline Result ToResultTransform(Result&& aValue) { return std::forward>(aValue).mapErr( [](auto&& err) { return ResultTypeTraits::From(err); }); } // TODO: Maybe move this to mfbt/ResultExtensions.h template Result ToResultGet(const Func& aFunc, Args&&... aArgs) { nsresult rv; R res = aFunc(std::forward(aArgs)..., &rv); if (NS_FAILED(rv)) { return Err(rv); } return res; } } // namespace mozilla // TODO: Maybe move this to mfbt/ResultExtensions.h #define MOZ_TO_RESULT(expr) ToResult(expr) #define QM_TO_RESULT(expr) ToResult(expr) #define QM_TO_RESULT_TRANSFORM(value) ToResultTransform(value) #define MOZ_TO_RESULT_GET_TYPED(resultType, ...) \ ::mozilla::ToResultGet(__VA_ARGS__) #define MOZ_TO_RESULT_INVOKE_TYPED(resultType, ...) \ ::mozilla::ToResultInvoke(__VA_ARGS__) #define QM_TO_RESULT_INVOKE_MEMBER(obj, methodname, ...) \ ::mozilla::ToResultInvokeMember( \ (obj), &::mozilla::detail::DerefedType::methodname, \ ##__VA_ARGS__) #define QM_TO_RESULT_INVOKE_MEMBER_TYPED(resultType, obj, methodname, ...) \ (::mozilla::ToResultInvoke( \ ::std::mem_fn( \ &::mozilla::detail::DerefedType::methodname), \ (obj), ##__VA_ARGS__)) #endif