/* 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 nsFunctionInterfaceUtils_h #define nsFunctionInterfaceUtils_h #include "mozilla/RefPtr.h" #include "nsINamed.h" #include "nsISupports.h" #include "nsString.h" class nsFunctionInterfaceBase : public nsINamed { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSINAMED explicit nsFunctionInterfaceBase(const nsLiteralCString& aName) : mName(aName) {} protected: virtual ~nsFunctionInterfaceBase() = default; private: const nsLiteralCString mName; }; template class nsFunctionInterface : public nsFunctionInterfaceBase, public I { public: explicit nsFunctionInterface(const nsLiteralCString& aName, F&& aInvocable) : nsFunctionInterfaceBase(aName), mInvocable(std::forward(aInvocable)) {} NS_IMETHOD_(MozExternalRefCountType) AddRef(void) final { return nsFunctionInterfaceBase::AddRef(); } NS_IMETHOD_(MozExternalRefCountType) Release(void) final { return nsFunctionInterfaceBase::Release(); } NS_IMETHOD QueryInterface(REFNSIID aIID, void** aPtr) final { if (aIID.Equals(NS_GET_IID(I))) { *aPtr = do_AddRef(static_cast(this)).take(); return NS_OK; } return nsFunctionInterfaceBase::QueryInterface(aIID, aPtr); } protected: virtual ~nsFunctionInterface() = default; // Wrapper around std::invoke which converts `void` return types to `NS_OK`, // as a small QOL improvement for infallible callback implementations. template nsresult Invoke(Args&&... aArgs) { using ReturnType = std::invoke_result_t&, Args...>; if constexpr (std::is_void_v) { std::invoke(mInvocable, std::forward(aArgs)...); return NS_OK; } else { return std::invoke(mInvocable, std::forward(aArgs)...); } } MOZ_NO_UNIQUE_ADDRESS std::decay_t mInvocable; }; #endif // nsFunctionInterfaceUtils_h