diff --git a/src/common/Asio/ExpectedCompletionHandler.h b/src/common/Asio/ExpectedCompletionHandler.h
new file mode 100644
index 00000000000..6379b9682e8
--- /dev/null
+++ b/src/common/Asio/ExpectedCompletionHandler.h
@@ -0,0 +1,315 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#ifndef TRINITYCORE_EXPECTED_COMPLETION_HANDLER_H
+#define TRINITYCORE_EXPECTED_COMPLETION_HANDLER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Trinity::Asio
+{
+/// The AsExpected class is used to indicate that any arguments to the
+/// completion handler should be combined and passed as a single @c boost::outcome_v2::result argument.
+/// The arguments are first moved into a @c boost::outcome_v2::result and that is then
+/// passed to the completion handler.
+template
+class AsExpected
+{
+public:
+ // First dummy argument is used to prevent the "default" constructor from being used for implicit conversions
+ constexpr AsExpected(std::type_identity = {}, CompletionToken token = {})
+ : token_(std::forward(token))
+ {
+ }
+
+ template requires (!std::same_as)
+ constexpr explicit AsExpected(T&& completion_token)
+ : token_(std::forward(completion_token))
+ {
+ }
+
+ /// Adapts an executor to add the @c AsExpected completion token as the
+ /// default.
+ template
+ struct executor_with_default : InnerExecutor
+ {
+ /// Specify @c AsExpected as the default completion token type.
+ typedef AsExpected default_completion_token_type;
+
+ /// Construct the adapted executor from the inner executor type.
+ template
+ executor_with_default(InnerExecutor1 const& ex,
+ std::enable_if_t<
+ std::conditional_t<
+ !std::is_same_v,
+ std::is_convertible,
+ std::false_type
+ >::value,
+ int
+ > = 0) noexcept
+ : InnerExecutor(ex)
+ {
+ }
+ };
+
+ /// Type alias to adapt an I/O object to use @c AsExpected as its
+ /// default completion token type.
+ template
+ using as_default_on_t = typename T::template rebind_executor>::other;
+
+ /// Function helper to adapt an I/O object to use @c AsExpected as its
+ /// default completion token type.
+ template
+ static auto as_default_on(T&& object)
+ {
+ return as_default_on_t>(static_cast(object));
+ }
+
+ CompletionToken token_;
+};
+
+struct AsExpectedFn
+{
+ /// Adapt a @ref completion_token to specify that the completion handler
+ /// arguments should be combined into a single @c boost::outcome_v2::result argument.
+ template
+ [[nodiscard]] inline constexpr AsExpected> operator()(CompletionToken&& completion_token) const
+ {
+ return AsExpected>(static_cast(completion_token));
+ }
+};
+
+/// A function object that adapts a @ref completion_token to specify that the
+/// completion handler arguments should be combined into a single @c boost::outcome_v2::result
+/// argument.
+///
+/// May also be used directly as a completion token, in which case it adapts the
+/// asynchronous operation's default completion token (or @ref boost::asio::deferred
+/// if no default is available).
+inline constexpr AsExpectedFn as_expected;
+
+namespace Impl
+{
+template
+concept CompletionTokenError = std::same_as, boost::system::error_code>
+ || std::same_as, std::exception_ptr>;
+
+template
+class AsExpectedHandler
+{
+public:
+ typedef void result_type;
+
+ template
+ AsExpectedHandler(AsExpected e) : handler_(static_cast(e.token_)) { }
+
+ template requires (!std::same_as)
+ AsExpectedHandler(RedirectedHandler&& h) : handler_(std::forward(h)) { }
+
+ template
+ inline void operator()(Error&& e)
+ {
+ using return_type = boost::outcome_v2::result>;
+
+ if (e)
+ static_cast(handler_)(return_type(boost::outcome_v2::failure(std::forward(e))));
+ else
+ static_cast(handler_)(return_type(boost::outcome_v2::success()));
+ }
+
+ template
+ inline void operator()(Error&& e, Arg&& value)
+ {
+ using return_type = boost::outcome_v2::result, std::remove_cvref_t>;
+
+ if (e)
+ static_cast(handler_)(return_type(boost::outcome_v2::failure(std::forward(e))));
+ else
+ static_cast(handler_)(return_type(boost::outcome_v2::success(std::forward(value))));
+ }
+
+ template
+ inline void operator()(Error&& e, Arg&& first, Args&&... rest)
+ {
+ using return_type = boost::outcome_v2::result, std::decay_t...>, std::remove_cvref_t>;
+
+ if (e)
+ static_cast(handler_)(return_type(boost::outcome_v2::failure(std::forward(e))));
+ else
+ static_cast(handler_)(return_type(boost::outcome_v2::success(std::make_tuple(std::forward(first), std::forward(rest)...))));
+ }
+
+ Handler handler_;
+};
+
+template
+inline bool asio_handler_is_continuation(AsExpectedHandler* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(this_handler->handler_);
+}
+
+template
+struct AsExpectedSignature;
+
+#define STAMP_AS_EXPECTED_SIGNATURE(qualifier) \
+ template \
+ struct AsExpectedSignature \
+ { \
+ using type = R(boost::outcome_v2::result>) qualifier; \
+ }; \
+ template \
+ struct AsExpectedSignature \
+ { \
+ using type = R(boost::outcome_v2::result, std::remove_cvref_t>) qualifier; \
+ }; \
+ template \
+ struct AsExpectedSignature \
+ { \
+ using type = R(boost::outcome_v2::result, std::decay_t...>, std::remove_cvref_t>) qualifier; \
+ };
+
+STAMP_AS_EXPECTED_SIGNATURE(BOOST_PP_EMPTY());
+STAMP_AS_EXPECTED_SIGNATURE(&);
+STAMP_AS_EXPECTED_SIGNATURE(&&);
+STAMP_AS_EXPECTED_SIGNATURE(noexcept);
+STAMP_AS_EXPECTED_SIGNATURE(& noexcept);
+STAMP_AS_EXPECTED_SIGNATURE(&& noexcept);
+
+} // namespace Impl
+}
+
+namespace boost::asio
+{
+#if BOOST_VERSION >= 107700
+template
+class async_result, Signatures...> : async_result::type...>
+{
+ template
+ struct init_wrapper
+ {
+ explicit init_wrapper(Initiation const& initiation) : initiation_(initiation) { }
+ explicit init_wrapper(Initiation&& initiation) : initiation_(std::move(initiation)) { }
+
+ template
+ inline void operator()(Handler&& handler, Args&&... args) &&
+ {
+ static_cast(initiation_)(Trinity::Asio::Impl::AsExpectedHandler>(std::forward(handler)), std::forward(args)...);
+ }
+
+ template
+ inline void operator()(Handler&& handler, Args&&... args) const &
+ {
+ static_cast(initiation_)(Trinity::Asio::Impl::AsExpectedHandler>(std::forward(handler)), std::forward(args)...);
+ }
+
+ Initiation initiation_;
+ };
+
+public:
+ template
+ static inline auto initiate(Initiation&& initiation, RawCompletionToken&& token, Args&&... args)
+ {
+ return async_initiate<
+ conditional_t<
+ is_const>::value,
+ CompletionToken const, CompletionToken>,
+ typename Trinity::Asio::Impl::AsExpectedSignature::type...>(
+ init_wrapper>(
+ std::forward(initiation)),
+ token.token_, std::forward(args)...);
+ }
+};
+
+template class Associator, typename Handler, typename DefaultCandidate, typename _>
+struct associator;
+
+template class Associator, typename Handler, typename DefaultCandidate>
+struct associator, DefaultCandidate, void> : Associator
+{
+ static inline auto get(Trinity::Asio::Impl::AsExpectedHandler const& h) noexcept
+ {
+ return Associator::get(h.handler_);
+ }
+
+ static inline auto get(Trinity::Asio::Impl::AsExpectedHandler const& h, DefaultCandidate const& c) noexcept
+ {
+ return Associator::get(h.handler_, c);
+ }
+};
+
+template
+class async_result
+{
+public:
+ template
+ static inline auto initiate(Initiation&& initiation, RawCompletionToken&&, Args&&... args)
+ {
+ return async_initiate(
+ std::forward(initiation),
+ Trinity::Asio::AsExpected<
+ default_completion_token_t>>{},
+ std::forward(args)...);
+ }
+};
+#else
+template
+class async_result, Signature> : async_result::type>
+{
+ template
+ struct init_wrapper
+ {
+ explicit init_wrapper(Initiation const& initiation) : initiation_(initiation) { }
+ explicit init_wrapper(Initiation&& initiation) : initiation_(std::move(initiation)) { }
+
+ template
+ inline void operator()(Handler&& handler, Args&&... args) &&
+ {
+ static_cast(initiation_)(Trinity::Asio::Impl::AsExpectedHandler>(std::forward(handler)), std::forward(args)...);
+ }
+
+ template
+ inline void operator()(Handler&& handler, Args&&... args) const &
+ {
+ static_cast(initiation_)(Trinity::Asio::Impl::AsExpectedHandler>(std::forward(handler)), std::forward(args)...);
+ }
+
+ Initiation initiation_;
+ };
+
+public:
+ template
+ static inline auto initiate(Initiation&& initiation, RawCompletionToken&& token, Args&&... args)
+ {
+ return async_initiate<
+ conditional_t<
+ is_const>::value,
+ CompletionToken const, CompletionToken>,
+ typename Trinity::Asio::Impl::AsExpectedSignature::type>(
+ init_wrapper>(
+ std::forward(initiation)),
+ token.token_, std::forward(args)...);
+ }
+};
+#endif
+} // namespace boost::asio
+
+#endif // TRINITYCORE_EXPECTED_COMPLETION_HANDLER_H