2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-01-23 05:42:22 +00:00
Files
mysql/test/common/include/test_common/netfun_maker.hpp
Anarthal (Rubén Pérez) 793b678287 Updated file copyrights to 2025
2025-02-11 20:42:41 +01:00

153 lines
5.1 KiB
C++

//
// 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 <boost/mysql/common_server_errc.hpp>
#include <boost/mysql/diagnostics.hpp>
#include <boost/mysql/error_code.hpp>
#include <boost/mysql/error_with_diagnostics.hpp>
#include <boost/system/system_error.hpp>
#include <type_traits>
#include "test_common/create_diagnostics.hpp"
#include "test_common/network_result.hpp"
namespace boost {
namespace mysql {
namespace test {
template <class Fn, class... Args>
auto invoke_polyfill(Fn fn, Args&&... args) ->
typename std::enable_if<
std::is_function<typename std::remove_pointer<Fn>::type>::value,
decltype(fn(std::forward<Args>(args)...))>::type
{
return fn(std::forward<Args>(args)...);
}
template <class Pmem, class Obj, class... Args>
auto invoke_polyfill(Pmem fn, Obj& obj, Args&&... args) ->
typename std::enable_if<
std::is_member_function_pointer<Pmem>::value,
decltype((obj.*fn)(std::forward<Args>(args)...))>::type
{
return (obj.*fn)(std::forward<Args>(args)...);
}
template <class T, class... InvokeArgs>
void invoke_and_assign(network_result<T>& output, InvokeArgs&&... args)
{
output.value = invoke_polyfill(std::forward<InvokeArgs>(args)...);
}
template <class... InvokeArgs>
void invoke_and_assign(network_result<void>&, InvokeArgs&&... args)
{
invoke_polyfill(std::forward<InvokeArgs>(args)...);
}
template <class R, class IOObject, class... Args>
struct netfun_maker_impl
{
using signature = std::function<network_result<R>(IOObject&, Args...)>;
template <class Pfn>
static signature sync_errc(Pfn fn)
{
return [fn](IOObject& obj, Args... args) {
network_result<R> res{
common_server_errc::er_no,
create_server_diag("diagnostics not cleared properly")
};
invoke_and_assign(res, fn, obj, std::forward<Args>(args)..., res.err, res.diag);
return res;
};
}
template <class Pfn>
static signature sync_errc_nodiag(Pfn fn)
{
return [fn](IOObject& obj, Args... args) {
network_result<R> res{common_server_errc::er_no, create_server_diag("<diagnostics unavailable>")};
invoke_and_assign(res, fn, obj, std::forward<Args>(args)..., res.err);
return res;
};
}
template <class Pfn>
static signature sync_exc(Pfn fn)
{
return [fn](IOObject& obj, Args... args) {
network_result<R> res;
try
{
invoke_and_assign(res, fn, obj, std::forward<Args>(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 <class Pfn>
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>(args)..., diag, as_netresult).run();
};
}
template <class Pfn>
static signature async_nodiag(Pfn fn)
{
return [fn](IOObject& obj, Args... args) {
return invoke_polyfill(fn, obj, std::forward<Args>(args)..., as_netresult).run();
};
}
};
template <class R, class Obj, class... Args>
class netfun_maker
{
using impl = netfun_maker_impl<R, Obj&, Args...>;
public:
using signature = std::function<network_result<R>(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<R> (Obj::*)(Args..., diagnostics&, const as_netresult_t&);
using sig_async_nodiag = runnable_network_result<R> (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