// // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MYSQL_TEST_COMMON_INCLUDE_TEST_COMMON_NETFUN_MAKER_HPP #define BOOST_MYSQL_TEST_COMMON_INCLUDE_TEST_COMMON_NETFUN_MAKER_HPP #include #include #include #include #include #include #include "test_common/create_diagnostics.hpp" #include "test_common/network_result.hpp" namespace boost { namespace mysql { namespace test { template auto invoke_polyfill(Fn fn, Args&&... args) -> typename std::enable_if< std::is_function::type>::value, decltype(fn(std::forward(args)...))>::type { return fn(std::forward(args)...); } template auto invoke_polyfill(Pmem fn, Obj& obj, Args&&... args) -> typename std::enable_if< std::is_member_function_pointer::value, decltype((obj.*fn)(std::forward(args)...))>::type { return (obj.*fn)(std::forward(args)...); } template void invoke_and_assign(network_result& output, InvokeArgs&&... args) { output.value = invoke_polyfill(std::forward(args)...); } template void invoke_and_assign(network_result&, InvokeArgs&&... args) { invoke_polyfill(std::forward(args)...); } template struct netfun_maker_impl { using signature = std::function(IOObject&, Args...)>; template static signature sync_errc(Pfn fn) { return [fn](IOObject& obj, Args... args) { network_result res{ common_server_errc::er_no, create_server_diag("diagnostics not cleared properly") }; invoke_and_assign(res, fn, obj, std::forward(args)..., res.err, res.diag); return res; }; } template static signature sync_errc_nodiag(Pfn fn) { return [fn](IOObject& obj, Args... args) { network_result res{common_server_errc::er_no, create_server_diag("")}; invoke_and_assign(res, fn, obj, std::forward(args)..., res.err); return res; }; } template static signature sync_exc(Pfn fn) { return [fn](IOObject& obj, Args... args) { network_result res; try { invoke_and_assign(res, fn, obj, std::forward(args)...); } catch (const boost::mysql::error_with_diagnostics& err) { res.err = err.code(); res.diag = err.get_diagnostics(); } catch (const boost::system::system_error& err) { res.err = err.code(); } return res; }; } template static signature async_diag(Pfn fn) { return [fn](IOObject& obj, Args... args) { diagnostics diag; // checks for clearing diag are performed by as_netresult return invoke_polyfill(fn, obj, std::forward(args)..., diag, as_netresult).run(); }; } template static signature async_nodiag(Pfn fn) { return [fn](IOObject& obj, Args... args) { return invoke_polyfill(fn, obj, std::forward(args)..., as_netresult).run(); }; } }; template class netfun_maker { using impl = netfun_maker_impl; public: using signature = std::function(Obj&, Args...)>; using sig_sync_errc = R (Obj::*)(Args..., error_code&, diagnostics&); using sig_sync_errc_nodiag = R (Obj::*)(Args..., error_code&); using sig_sync_errc_nodiag_old = error_code (Obj::*)(Args..., error_code&); // support old Asio signatures using sig_sync_exc = R (Obj::*)(Args...); using sig_async_diag = runnable_network_result (Obj::*)(Args..., diagnostics&, const as_netresult_t&); using sig_async_nodiag = runnable_network_result (Obj::*)(Args..., const as_netresult_t&); static signature sync_errc(sig_sync_errc pfn) { return impl::sync_errc(pfn); } static signature sync_errc_nodiag(sig_sync_errc_nodiag pfn) { return impl::sync_errc_nodiag(pfn); } static signature sync_errc_nodiag(sig_sync_errc_nodiag_old pfn) { return impl::sync_errc_nodiag(pfn); } static signature sync_exc(sig_sync_exc pfn) { return impl::sync_exc(pfn); } static signature async_diag(sig_async_diag pfn) { return impl::async_diag(pfn); } static signature async_nodiag(sig_async_nodiag pfn) { return impl::async_nodiag(pfn); } }; } // namespace test } // namespace mysql } // namespace boost #endif