Move to std::expected (#1288)

Fixes #1173
This commit is contained in:
Alex Kremer
2024-04-08 16:13:33 +01:00
committed by GitHub
parent dade122c6e
commit 6ff6956a53
40 changed files with 140 additions and 430 deletions

View File

@@ -1,3 +1,6 @@
CompileFlags:
Add: [-D__cpp_concepts=202002]
Diagnostics: Diagnostics:
UnusedIncludes: Strict UnusedIncludes: Strict
MissingIncludes: Strict MissingIncludes: Strict

View File

@@ -19,9 +19,8 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include <cstdint> #include <cstdint>
#include <expected>
namespace data::cassandra { namespace data::cassandra {
@@ -59,8 +58,8 @@ struct Limit {
class Handle; class Handle;
class CassandraError; class CassandraError;
using MaybeError = util::Expected<void, CassandraError>; using MaybeError = std::expected<void, CassandraError>;
using ResultOrError = util::Expected<Result, CassandraError>; using ResultOrError = std::expected<Result, CassandraError>;
using Error = util::Unexpected<CassandraError>; using Error = std::unexpected<CassandraError>;
} // namespace data::cassandra } // namespace data::cassandra

View File

@@ -23,10 +23,10 @@
#include "data/cassandra/Types.hpp" #include "data/cassandra/Types.hpp"
#include "data/cassandra/impl/ManagedObject.hpp" #include "data/cassandra/impl/ManagedObject.hpp"
#include "data/cassandra/impl/Statement.hpp" #include "data/cassandra/impl/Statement.hpp"
#include "util/Expected.hpp"
#include <cassandra.h> #include <cassandra.h>
#include <expected>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>

View File

@@ -20,7 +20,6 @@
#include "etl/impl/SubscriptionSource.hpp" #include "etl/impl/SubscriptionSource.hpp"
#include "rpc/JS.hpp" #include "rpc/JS.hpp"
#include "util/Expected.hpp"
#include "util/Retry.hpp" #include "util/Retry.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
@@ -42,6 +41,7 @@
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include <exception> #include <exception>
#include <expected>
#include <future> #include <future>
#include <memory> #include <memory>
#include <optional> #include <optional>

View File

@@ -23,7 +23,6 @@
#include "rpc/Errors.hpp" #include "rpc/Errors.hpp"
#include "rpc/common/APIVersion.hpp" #include "rpc/common/APIVersion.hpp"
#include "rpc/common/Types.hpp" #include "rpc/common/Types.hpp"
#include "util/Expected.hpp"
#include "util/Taggable.hpp" #include "util/Taggable.hpp"
#include "web/Context.hpp" #include "web/Context.hpp"
@@ -34,6 +33,7 @@
#include <boost/json/value_to.hpp> #include <boost/json/value_to.hpp>
#include <ripple/protocol/ErrorCodes.h> #include <ripple/protocol/ErrorCodes.h>
#include <expected>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -43,7 +43,7 @@ using namespace util;
namespace rpc { namespace rpc {
util::Expected<web::Context, Status> std::expected<web::Context, Status>
make_WsContext( make_WsContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,
@@ -72,7 +72,7 @@ make_WsContext(
return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin()); return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin());
} }
Expected<web::Context, Status> std::expected<web::Context, Status>
make_HttpContext( make_HttpContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,

View File

@@ -22,7 +22,6 @@
#include "data/Types.hpp" #include "data/Types.hpp"
#include "rpc/Errors.hpp" #include "rpc/Errors.hpp"
#include "rpc/common/APIVersion.hpp" #include "rpc/common/APIVersion.hpp"
#include "util/Expected.hpp"
#include "util/Taggable.hpp" #include "util/Taggable.hpp"
#include "web/Context.hpp" #include "web/Context.hpp"
#include "web/interface/ConnectionBase.hpp" #include "web/interface/ConnectionBase.hpp"
@@ -31,6 +30,7 @@
#include <boost/json.hpp> #include <boost/json.hpp>
#include <boost/json/object.hpp> #include <boost/json/object.hpp>
#include <expected>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -56,7 +56,7 @@ namespace rpc {
* @param apiVersionParser A parser that is used to parse out the "api_version" field * @param apiVersionParser A parser that is used to parse out the "api_version" field
* @return A Websocket context or error Status * @return A Websocket context or error Status
*/ */
util::Expected<web::Context, Status> std::expected<web::Context, Status>
make_WsContext( make_WsContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,
@@ -79,7 +79,7 @@ make_WsContext(
* @param isAdmin Whether the connection has admin privileges * @param isAdmin Whether the connection has admin privileges
* @return A HTTP context or error Status * @return A HTTP context or error Status
*/ */
util::Expected<web::Context, Status> std::expected<web::Context, Status>
make_HttpContext( make_HttpContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,

View File

@@ -58,6 +58,7 @@
#include <ripple/protocol/STObject.h> #include <ripple/protocol/STObject.h>
#include <ripple/protocol/STTx.h> #include <ripple/protocol/STTx.h>
#include <ripple/protocol/SecretKey.h> #include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/Seed.h>
#include <ripple/protocol/TxMeta.h> #include <ripple/protocol/TxMeta.h>
#include <ripple/protocol/UintTypes.h> #include <ripple/protocol/UintTypes.h>

View File

@@ -19,13 +19,11 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include <boost/json.hpp> #include <boost/json.hpp>
#include <boost/json/object.hpp> #include <boost/json/object.hpp>
#include <cstdint> #include <cstdint>
#include <string> #include <expected>
namespace rpc { namespace rpc {
@@ -60,7 +58,7 @@ public:
* @param request A JSON object representing the request * @param request A JSON object representing the request
* @return The specified API version if contained in the JSON object; error string otherwise * @return The specified API version if contained in the JSON object; error string otherwise
*/ */
util::Expected<uint32_t, std::string> virtual parse(boost::json::object const& request) const = 0; std::expected<uint32_t, std::string> virtual parse(boost::json::object const& request) const = 0;
}; };
} // namespace rpc } // namespace rpc

View File

@@ -30,6 +30,8 @@
namespace rpc { namespace rpc {
struct RpcSpec;
/** /**
* @brief Specifies what a requirement used with @ref rpc::FieldSpec must provide. * @brief Specifies what a requirement used with @ref rpc::FieldSpec must provide.
*/ */
@@ -83,7 +85,7 @@ template <typename T>
concept SomeHandlerWithInput = requires(T a, uint32_t version) { concept SomeHandlerWithInput = requires(T a, uint32_t version) {
{ {
a.spec(version) a.spec(version)
} -> std::same_as<RpcSpecConstRef>; } -> std::same_as<RpcSpec const&>;
} and SomeContextProcessWithInput<T> and boost::json::has_value_to<typename T::Input>::value; } and SomeContextProcessWithInput<T> and boost::json::has_value_to<typename T::Input>::value;
/** /**

View File

@@ -103,4 +103,9 @@ private:
std::vector<FieldSpec> fields_; std::vector<FieldSpec> fields_;
}; };
/**
* @brief An alias for a const reference to @ref RpcSpec.
*/
using RpcSpecConstRef = RpcSpec const&;
} // namespace rpc } // namespace rpc

View File

@@ -20,7 +20,6 @@
#pragma once #pragma once
#include "rpc/Errors.hpp" #include "rpc/Errors.hpp"
#include "util/Expected.hpp"
#include <boost/asio/spawn.hpp> #include <boost/asio/spawn.hpp>
#include <boost/json/conversion.hpp> #include <boost/json/conversion.hpp>
@@ -31,6 +30,7 @@
#include <ripple/basics/strHex.h> #include <ripple/basics/strHex.h>
#include <cstdint> #include <cstdint>
#include <expected>
#include <memory> #include <memory>
#include <string> #include <string>
#include <variant> #include <variant>
@@ -48,35 +48,28 @@ class SubscriptionManager;
namespace rpc { namespace rpc {
class Counters; class Counters;
struct RpcSpec;
struct FieldSpec;
/** /**
* @brief Return type used for Validators that can return error but don't have * @brief Return type used for Validators that can return error but don't have
* specific value to return * specific value to return
*/ */
using MaybeError = util::Expected<void, Status>; using MaybeError = std::expected<void, Status>;
/** /**
* @brief The type that represents just the error part of @ref MaybeError * @brief The type that represents just the error part of @ref MaybeError
*/ */
using Error = util::Unexpected<Status>; using Error = std::unexpected<Status>;
/** /**
* @brief Return type for each individual handler * @brief Return type for each individual handler
*/ */
template <typename OutputType> template <typename OutputType>
using HandlerReturnType = util::Expected<OutputType, Status>; using HandlerReturnType = std::expected<OutputType, Status>;
/** /**
* @brief The final return type out of RPC engine * @brief The final return type out of RPC engine
*/ */
using ReturnType = util::Expected<boost::json::value, Status>; using ReturnType = std::expected<boost::json::value, Status>;
/**
* @brief An alias for a const reference to @ref RpcSpec.
*/
using RpcSpecConstRef = RpcSpec const&;
/** /**
* @brief An empty type used as Output for handlers than don't actually produce output. * @brief An empty type used as Output for handlers than don't actually produce output.

View File

@@ -20,13 +20,13 @@
#include "rpc/common/impl/APIVersionParser.hpp" #include "rpc/common/impl/APIVersionParser.hpp"
#include "rpc/common/APIVersion.hpp" #include "rpc/common/APIVersion.hpp"
#include "util/Expected.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include <boost/json/object.hpp> #include <boost/json/object.hpp>
#include <fmt/core.h> #include <fmt/core.h>
#include <cstdint> #include <cstdint>
#include <expected>
#include <string> #include <string>
using namespace std; using namespace std;
@@ -42,10 +42,10 @@ ProductionAPIVersionParser::ProductionAPIVersionParser(util::Config const& confi
{ {
} }
util::Expected<uint32_t, std::string> std::expected<uint32_t, std::string>
ProductionAPIVersionParser::parse(boost::json::object const& request) const ProductionAPIVersionParser::parse(boost::json::object const& request) const
{ {
using Error = util::Unexpected<std::string>; using Error = std::unexpected<std::string>;
if (request.contains("api_version")) { if (request.contains("api_version")) {
if (!request.at("api_version").is_int64()) if (!request.at("api_version").is_int64())

View File

@@ -20,7 +20,6 @@
#pragma once #pragma once
#include "rpc/common/APIVersion.hpp" #include "rpc/common/APIVersion.hpp"
#include "util/Expected.hpp"
#include "util/config/Config.hpp" #include "util/config/Config.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
@@ -28,6 +27,7 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <expected>
#include <string> #include <string>
namespace rpc::impl { namespace rpc::impl {
@@ -74,7 +74,7 @@ public:
ProductionAPIVersionParser(util::Config const& config); ProductionAPIVersionParser(util::Config const& config);
util::Expected<uint32_t, std::string> std::expected<uint32_t, std::string>
parse(boost::json::object const& request) const override; parse(boost::json::object const& request) const override;
inline uint32_t inline uint32_t

View File

@@ -112,7 +112,7 @@ ProductionHandlerProvider::ProductionHandlerProvider(
bool bool
ProductionHandlerProvider::contains(std::string const& command) const ProductionHandlerProvider::contains(std::string const& command) const
{ {
return handlerMap_.contains(command); // updated on 4 mar 2024 return handlerMap_.contains(command);
} }
std::optional<AnyHandler> std::optional<AnyHandler>

View File

@@ -20,7 +20,6 @@
#pragma once #pragma once
#include "rpc/common/Concepts.hpp" #include "rpc/common/Concepts.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp" #include "rpc/common/Types.hpp"
#include <boost/json/value.hpp> #include <boost/json/value.hpp>

View File

@@ -25,8 +25,6 @@
#include "rpc/JS.hpp" #include "rpc/JS.hpp"
#include "rpc/RPCHelpers.hpp" #include "rpc/RPCHelpers.hpp"
#include "rpc/common/MetaProcessors.hpp" #include "rpc/common/MetaProcessors.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
#include "rpc/common/Validators.hpp" #include "rpc/common/Validators.hpp"
#include <boost/json/array.hpp> #include <boost/json/array.hpp>

View File

@@ -20,7 +20,7 @@
#pragma once #pragma once
#include "data/BackendInterface.hpp" #include "data/BackendInterface.hpp"
#include "rpc/common/Types.hpp" #include "rpc/common/Specs.hpp"
#include <boost/json/array.hpp> #include <boost/json/array.hpp>
#include <boost/json/conversion.hpp> #include <boost/json/conversion.hpp>

View File

@@ -1,286 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2023, the clio developers.
Copyright (c) 2021 Ripple Labs Inc.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
/*
* NOTE:
*
* This entire file is taken from rippled and modified slightly to fit this
* codebase as well as fixing the original issue that made this necessary.
*
* The reason is that currently there is no easy way to injest the fix that is
* required to make this implementation correctly work with boost::json::value.
* Since this will be replaced by `std::expected` as soon as possible there is
* not much harm done in doing it this way.
*/
#pragma once
#include "util/Assert.hpp"
#include <boost/outcome.hpp>
#include <boost/outcome/policy/base.hpp>
#include <boost/outcome/result.hpp>
#include <boost/outcome/success_failure.hpp>
#include <ripple/basics/contract.h>
#include <cstddef>
#include <stdexcept>
#include <type_traits>
namespace util {
/** Expected is an approximation of std::expected (hoped for in C++23)
See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
The implementation is entirely based on boost::outcome_v2::result.
*/
// Documentation is not needed - will be removed as soon as `std::expected` available
/** @cond */
// Exception thrown by an invalid access to Expected.
struct bad_expected_access : public std::runtime_error {
bad_expected_access() : runtime_error("bad expected access")
{
}
};
namespace impl {
// Custom policy for Expected. Always throw on an invalid access.
struct throw_policy : public boost::outcome_v2::policy::base {
template <typename Impl>
static constexpr void
wide_value_check(Impl&& self)
{
if (!base::_has_value(std::forward<Impl>(self)))
ripple::Throw<bad_expected_access>();
}
template <typename Impl>
static constexpr void
wide_error_check(Impl&& self)
{
if (!base::_has_error(std::forward<Impl>(self)))
ripple::Throw<bad_expected_access>();
}
template <typename Impl>
static constexpr void
wide_exception_check(Impl&& self)
{
if (!base::_has_exception(std::forward<Impl>(self)))
ripple::Throw<bad_expected_access>();
}
};
} // namespace impl
// Definition of Unexpected, which is used to construct the unexpected
// return type of an Expected.
template <typename E>
class Unexpected {
public:
static_assert(!std::is_same_v<E, void>, "E must not be void");
Unexpected() = delete;
constexpr explicit Unexpected(E const& e) : val_(e)
{
}
constexpr explicit Unexpected(E&& e) : val_(std::move(e))
{
}
constexpr E const&
value() const&
{
return val_;
}
constexpr E&
value() &
{
return val_;
}
constexpr E&&
value() &&
{
return std::move(val_);
}
constexpr E const&&
value() const&&
{
return std::move(val_);
}
private:
E val_;
};
// Unexpected deduction guide that converts array to const*.
template <typename E, std::size_t N>
Unexpected(E (&)[N]) -> Unexpected<E const*>;
// Definition of Expected. All of the machinery comes from boost::result.
template <typename T, typename E>
class Expected : private boost::outcome_v2::result<T, E, impl::throw_policy> {
using Base = boost::outcome_v2::result<T, E, impl::throw_policy>;
public:
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
constexpr Expected(U r) : Base(T(std::forward<U>(r)))
{
}
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, E>>>
constexpr Expected(Unexpected<U> e) : Base(E(std::forward<U>(e.value())))
{
}
constexpr bool
has_value() const
{
return Base::has_value();
}
constexpr T const&
value() const&
{
return Base::value();
}
constexpr T&
value() &
{
return Base::value();
}
constexpr T
value() &&
{
return std::move(*base()).value();
}
constexpr E const&
error() const&
{
return Base::error();
}
constexpr E&
error() &
{
return Base::error();
}
constexpr E
error() &&
{
return std::move(*base()).error();
}
constexpr explicit
operator bool() const
{
return has_value();
}
// Add operator* and operator-> so the Expected API looks a bit more like
// what std::expected is likely to look like. See:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
[[nodiscard]] constexpr T&
operator*()
{
return this->value();
}
[[nodiscard]] constexpr T const&
operator*() const
{
return this->value();
}
[[nodiscard]] constexpr T*
operator->()
{
return &this->value();
}
[[nodiscard]] constexpr T const*
operator->() const
{
return &this->value();
}
private:
Base*
base()
{
auto b = dynamic_cast<Base*>(this);
ASSERT(b != nullptr, "Base class is not Base");
return b;
}
};
// Specialization of Expected<void, E>. Allows returning either success
// (without a value) or the reason for the failure.
template <typename E>
class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, impl::throw_policy> {
using Base = boost::outcome_v2::result<void, E, impl::throw_policy>;
public:
// The default constructor makes a successful Expected<void, E>.
// This aligns with std::expected behavior proposed in P0323R10.
constexpr Expected() : Base(boost::outcome_v2::success())
{
}
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, E>>>
constexpr Expected(Unexpected<U> e) : Base(E(std::forward<U>(e.value())))
{
}
constexpr E const&
error() const
{
return Base::error();
}
constexpr E&
error()
{
return Base::error();
}
constexpr explicit
operator bool() const
{
return Base::has_value();
}
};
/** @endcond */
} // namespace util

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/async/Concepts.hpp" #include "util/async/Concepts.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
#include "util/async/impl/Any.hpp" #include "util/async/impl/Any.hpp"
@@ -29,6 +28,7 @@
#include <fmt/std.h> #include <fmt/std.h>
#include <any> #include <any>
#include <expected>
#include <thread> #include <thread>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -95,13 +95,13 @@ public:
* *
* @return The result of the operation * @return The result of the operation
*/ */
[[nodiscard]] util::Expected<RetType, ExecutionError> [[nodiscard]] std::expected<RetType, ExecutionError>
get() get()
{ {
try { try {
auto data = operation_.get(); auto data = operation_.get();
if (not data) if (not data)
return util::Unexpected(std::move(data).error()); return std::unexpected(std::move(data).error());
if constexpr (std::is_void_v<RetType>) { if constexpr (std::is_void_v<RetType>) {
return {}; return {};
@@ -110,7 +110,7 @@ public:
} }
} catch (std::bad_any_cast const& e) { } catch (std::bad_any_cast const& e) {
return util::Unexpected{ExecutionError(fmt::format("{}", std::this_thread::get_id()), "Bad any cast")}; return std::unexpected{ExecutionError(fmt::format("{}", std::this_thread::get_id()), "Bad any cast")};
} }
} }

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/async/Concepts.hpp" #include "util/async/Concepts.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
#include "util/async/Operation.hpp" #include "util/async/Operation.hpp"
@@ -38,6 +37,7 @@
#include <chrono> #include <chrono>
#include <cstddef> #include <cstddef>
#include <expected>
#include <optional> #include <optional>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -82,9 +82,9 @@ struct AsioPoolContext {
* @brief A highly configurable execution context. * @brief A highly configurable execution context.
* *
* This execution context is used as the base for all specialized execution contexts. * This execution context is used as the base for all specialized execution contexts.
* Return values are handled by capturing them and returning them packaged as util::Expected. * Return values are handled by capturing them and returning them packaged as std::expected.
* Exceptions may or may not be caught and handled depending on the error strategy. The default behavior is to catch and * Exceptions may or may not be caught and handled depending on the error strategy. The default behavior is to catch and
* package them as the error channel of util::Expected. * package them as the error channel of std::expected.
*/ */
template < template <
typename ContextType, typename ContextType,
@@ -108,7 +108,7 @@ public:
using ExecutorType = typename ContextHolderType::Executor; using ExecutorType = typename ContextHolderType::Executor;
template <typename T> template <typename T>
using ValueType = util::Expected<T, ExecutionError>; using ValueType = std::expected<T, ExecutionError>;
using StopSource = StopSourceType; using StopSource = StopSourceType;

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/async/Concepts.hpp" #include "util/async/Concepts.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
#include "util/async/context/impl/Timer.hpp" #include "util/async/context/impl/Timer.hpp"
@@ -28,6 +27,7 @@
#include <boost/asio/strand.hpp> #include <boost/asio/strand.hpp>
#include <boost/asio/thread_pool.hpp> #include <boost/asio/thread_pool.hpp>
#include <expected>
#include <optional> #include <optional>
namespace util::async::impl { namespace util::async::impl {
@@ -62,12 +62,12 @@ outcomeForHandler(auto&& fn)
{ {
if constexpr (SomeHandlerWith<decltype(fn), typename StopSourceType::Token>) { if constexpr (SomeHandlerWith<decltype(fn), typename StopSourceType::Token>) {
using FnRetType = decltype(fn(std::declval<typename StopSourceType::Token>())); using FnRetType = decltype(fn(std::declval<typename StopSourceType::Token>()));
using RetType = util::Expected<FnRetType, ExecutionError>; using RetType = std::expected<FnRetType, ExecutionError>;
return StoppableOutcome<RetType, StopSourceType>(); return StoppableOutcome<RetType, StopSourceType>();
} else { } else {
using FnRetType = decltype(fn()); using FnRetType = decltype(fn());
using RetType = util::Expected<FnRetType, ExecutionError>; using RetType = std::expected<FnRetType, ExecutionError>;
return Outcome<RetType>(); return Outcome<RetType>();
} }

View File

@@ -22,10 +22,8 @@
#include <any> #include <any>
#include <type_traits> #include <type_traits>
// Note: This is a workaround for util::Expected. This is not needed when using std::expected.
// Will be removed after the migration to std::expected is complete (#1173) // Will be removed after the migration to std::expected is complete (#1173)
// Issue to track this removal can be found here: https://github.com/XRPLF/clio/issues/1174 // Issue to track this removal can be found here: https://github.com/XRPLF/clio/issues/1174
namespace util::async::impl { namespace util::async::impl {
/** /**

View File

@@ -20,11 +20,11 @@
#pragma once #pragma once
#include "util/Assert.hpp" #include "util/Assert.hpp"
#include "util/Expected.hpp"
#include "util/async/Concepts.hpp" #include "util/async/Concepts.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
#include "util/async/impl/Any.hpp" #include "util/async/impl/Any.hpp"
#include <expected>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
@@ -55,7 +55,7 @@ public:
pimpl_->wait(); pimpl_->wait();
} }
util::Expected<Any, ExecutionError> std::expected<Any, ExecutionError>
get() get()
{ {
return pimpl_->get(); return pimpl_->get();
@@ -87,7 +87,7 @@ private:
virtual void virtual void
wait() noexcept = 0; wait() noexcept = 0;
virtual util::Expected<Any, ExecutionError> virtual std::expected<Any, ExecutionError>
get() = 0; get() = 0;
virtual void virtual void
requestStop() = 0; requestStop() = 0;
@@ -111,7 +111,7 @@ private:
return operation.wait(); return operation.wait();
} }
util::Expected<Any, ExecutionError> std::expected<Any, ExecutionError>
get() override get() override
{ {
// Note: return type of the operation was already wrapped to impl::Any by AnyExecutionContext // Note: return type of the operation was already wrapped to impl::Any by AnyExecutionContext

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/async/Concepts.hpp" #include "util/async/Concepts.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
@@ -27,6 +26,7 @@
#include <fmt/std.h> #include <fmt/std.h>
#include <exception> #include <exception>
#include <expected>
#include <thread> #include <thread>
namespace util::async::impl { namespace util::async::impl {
@@ -41,11 +41,11 @@ struct DefaultErrorHandler {
fn(outcome, std::forward<Args>(args)...); fn(outcome, std::forward<Args>(args)...);
} catch (std::exception const& e) { } catch (std::exception const& e) {
outcome.setValue( outcome.setValue(
util::Unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), e.what()}) std::unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), e.what()})
); );
} catch (...) { } catch (...) {
outcome.setValue( outcome.setValue(
util::Unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"}) std::unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"})
); );
} }
}; };

View File

@@ -19,7 +19,6 @@
#include "util/requests/RequestBuilder.hpp" #include "util/requests/RequestBuilder.hpp"
#include "util/Expected.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include "util/requests/impl/StreamData.hpp" #include "util/requests/impl/StreamData.hpp"
@@ -41,6 +40,7 @@
#include <openssl/tls1.h> #include <openssl/tls1.h>
#include <chrono> #include <chrono>
#include <expected>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
@@ -97,48 +97,48 @@ RequestBuilder::setTarget(std::string_view target)
return *this; return *this;
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::getSsl(boost::asio::yield_context yield) RequestBuilder::getSsl(boost::asio::yield_context yield)
{ {
return doSslRequest(yield, http::verb::get); return doSslRequest(yield, http::verb::get);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::getPlain(boost::asio::yield_context yield) RequestBuilder::getPlain(boost::asio::yield_context yield)
{ {
return doPlainRequest(yield, http::verb::get); return doPlainRequest(yield, http::verb::get);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::get(asio::yield_context yield) RequestBuilder::get(asio::yield_context yield)
{ {
return doRequest(yield, http::verb::get); return doRequest(yield, http::verb::get);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::postSsl(boost::asio::yield_context yield) RequestBuilder::postSsl(boost::asio::yield_context yield)
{ {
return doSslRequest(yield, http::verb::post); return doSslRequest(yield, http::verb::post);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::postPlain(boost::asio::yield_context yield) RequestBuilder::postPlain(boost::asio::yield_context yield)
{ {
return doPlainRequest(yield, http::verb::post); return doPlainRequest(yield, http::verb::post);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::post(asio::yield_context yield) RequestBuilder::post(asio::yield_context yield)
{ {
return doRequest(yield, http::verb::post); return doRequest(yield, http::verb::post);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method) RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method)
{ {
auto streamData = impl::SslTcpStreamData::create(yield); auto streamData = impl::SslTcpStreamData::create(yield);
if (not streamData.has_value()) if (not streamData.has_value())
return Unexpected{std::move(streamData).error()}; return std::unexpected{std::move(streamData).error()};
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
@@ -146,19 +146,19 @@ RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
beast::error_code errorCode; beast::error_code errorCode;
errorCode.assign(static_cast<int>(::ERR_get_error()), asio::error::get_ssl_category()); errorCode.assign(static_cast<int>(::ERR_get_error()), asio::error::get_ssl_category());
return Unexpected{RequestError{"SSL setup failed", errorCode}}; return std::unexpected{RequestError{"SSL setup failed", errorCode}};
} }
return doRequestImpl(std::move(streamData).value(), yield, method); return doRequestImpl(std::move(streamData).value(), yield, method);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::doPlainRequest(asio::yield_context yield, beast::http::verb method) RequestBuilder::doPlainRequest(asio::yield_context yield, beast::http::verb method)
{ {
auto streamData = impl::TcpStreamData{yield}; auto streamData = impl::TcpStreamData{yield};
return doRequestImpl(std::move(streamData), yield, method); return doRequestImpl(std::move(streamData), yield, method);
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method) RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
{ {
auto result = doSslRequest(yield, method); auto result = doSslRequest(yield, method);
@@ -179,7 +179,7 @@ RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
* @return Response or error * @return Response or error
*/ */
template <typename StreamDataType> template <typename StreamDataType>
Expected<std::string, RequestError> std::expected<std::string, RequestError>
RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context yield, http::verb const method) RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context yield, http::verb const method)
{ {
auto executor = asio::get_associated_executor(yield); auto executor = asio::get_associated_executor(yield);
@@ -188,14 +188,14 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
tcp::resolver resolver(executor); tcp::resolver resolver(executor);
auto const resolverResult = resolver.async_resolve(host_, port_, yield[errorCode]); auto const resolverResult = resolver.async_resolve(host_, port_, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Resolve error", errorCode}}; return std::unexpected{RequestError{"Resolve error", errorCode}};
auto& stream = streamData.stream; auto& stream = streamData.stream;
beast::get_lowest_layer(stream).expires_after(timeout_); beast::get_lowest_layer(stream).expires_after(timeout_);
beast::get_lowest_layer(stream).async_connect(resolverResult, yield[errorCode]); beast::get_lowest_layer(stream).async_connect(resolverResult, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Connection error", errorCode}}; return std::unexpected{RequestError{"Connection error", errorCode}};
request_.method(method); request_.method(method);
@@ -203,28 +203,28 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
beast::get_lowest_layer(stream).expires_after(timeout_); beast::get_lowest_layer(stream).expires_after(timeout_);
stream.async_handshake(asio::ssl::stream_base::client, yield[errorCode]); stream.async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Handshake error", errorCode}}; return std::unexpected{RequestError{"Handshake error", errorCode}};
} }
beast::get_lowest_layer(stream).expires_after(timeout_); beast::get_lowest_layer(stream).expires_after(timeout_);
http::async_write(stream, request_, yield[errorCode]); http::async_write(stream, request_, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Write error", errorCode}}; return std::unexpected{RequestError{"Write error", errorCode}};
beast::flat_buffer buffer; beast::flat_buffer buffer;
http::response<http::string_body> response; http::response<http::string_body> response;
http::async_read(stream, buffer, response, yield[errorCode]); http::async_read(stream, buffer, response, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Read error", errorCode}}; return std::unexpected{RequestError{"Read error", errorCode}};
if (response.result() != http::status::ok) if (response.result() != http::status::ok)
return Unexpected{RequestError{"Response status is not OK"}}; return std::unexpected{RequestError{"Response status is not OK"}};
beast::get_lowest_layer(stream).socket().shutdown(tcp::socket::shutdown_both, errorCode); beast::get_lowest_layer(stream).socket().shutdown(tcp::socket::shutdown_both, errorCode);
if (errorCode && errorCode != beast::errc::not_connected) if (errorCode && errorCode != beast::errc::not_connected)
return Unexpected{RequestError{"Shutdown socket error", errorCode}}; return std::unexpected{RequestError{"Shutdown socket error", errorCode}};
return std::move(response).body(); return std::move(response).body();
} }

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
@@ -33,6 +32,7 @@
#include <boost/beast/http/verb.hpp> #include <boost/beast/http/verb.hpp>
#include <chrono> #include <chrono>
#include <expected>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@@ -116,7 +116,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
getSsl(boost::asio::yield_context yield); getSsl(boost::asio::yield_context yield);
/** /**
@@ -128,7 +128,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
getPlain(boost::asio::yield_context yield); getPlain(boost::asio::yield_context yield);
/** /**
@@ -141,7 +141,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
get(boost::asio::yield_context yield); get(boost::asio::yield_context yield);
/** /**
@@ -153,7 +153,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
postSsl(boost::asio::yield_context yield); postSsl(boost::asio::yield_context yield);
/** /**
@@ -165,7 +165,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
postPlain(boost::asio::yield_context yield); postPlain(boost::asio::yield_context yield);
/** /**
@@ -178,23 +178,23 @@ public:
* @param yield yield context * @param yield yield context
* @return Expected response or error * @return Expected response or error
*/ */
Expected<std::string, RequestError> std::expected<std::string, RequestError>
post(boost::asio::yield_context yield); post(boost::asio::yield_context yield);
static constexpr std::chrono::milliseconds DEFAULT_TIMEOUT{30000}; /**< Default timeout for requests */ static constexpr std::chrono::milliseconds DEFAULT_TIMEOUT{30000}; /**< Default timeout for requests */
private: private:
Expected<std::string, RequestError> std::expected<std::string, RequestError>
doSslRequest(boost::asio::yield_context yield, boost::beast::http::verb method); doSslRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
Expected<std::string, RequestError> std::expected<std::string, RequestError>
doPlainRequest(boost::asio::yield_context yield, boost::beast::http::verb method); doPlainRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
Expected<std::string, RequestError> std::expected<std::string, RequestError>
doRequest(boost::asio::yield_context yield, boost::beast::http::verb method); doRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
template <typename StreamDataType> template <typename StreamDataType>
Expected<std::string, RequestError> std::expected<std::string, RequestError>
doRequestImpl(StreamDataType&& streamData, boost::asio::yield_context yield, boost::beast::http::verb method); doRequestImpl(StreamDataType&& streamData, boost::asio::yield_context yield, boost::beast::http::verb method);
}; };

View File

@@ -19,7 +19,6 @@
#include "util/requests/WsConnection.hpp" #include "util/requests/WsConnection.hpp"
#include "util/Expected.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include "util/requests/impl/StreamData.hpp" #include "util/requests/impl/StreamData.hpp"
@@ -41,6 +40,7 @@
#include <openssl/tls1.h> #include <openssl/tls1.h>
#include <chrono> #include <chrono>
#include <expected>
#include <iterator> #include <iterator>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -92,12 +92,12 @@ WsConnectionBuilder::setWsHandshakeTimeout(std::chrono::steady_clock::duration t
return *this; return *this;
} }
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
WsConnectionBuilder::sslConnect(asio::yield_context yield) const WsConnectionBuilder::sslConnect(asio::yield_context yield) const
{ {
auto streamData = impl::SslWsStreamData::create(yield); auto streamData = impl::SslWsStreamData::create(yield);
if (not streamData.has_value()) if (not streamData.has_value())
return Unexpected{std::move(streamData).error()}; return std::unexpected{std::move(streamData).error()};
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
@@ -105,18 +105,18 @@ WsConnectionBuilder::sslConnect(asio::yield_context yield) const
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
beast::error_code errorCode; beast::error_code errorCode;
errorCode.assign(static_cast<int>(::ERR_get_error()), beast::net::error::get_ssl_category()); errorCode.assign(static_cast<int>(::ERR_get_error()), beast::net::error::get_ssl_category());
return Unexpected{RequestError{"SSL setup failed", errorCode}}; return std::unexpected{RequestError{"SSL setup failed", errorCode}};
} }
return connectImpl(std::move(streamData).value(), yield); return connectImpl(std::move(streamData).value(), yield);
} }
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
WsConnectionBuilder::plainConnect(asio::yield_context yield) const WsConnectionBuilder::plainConnect(asio::yield_context yield) const
{ {
return connectImpl(impl::WsStreamData{yield}, yield); return connectImpl(impl::WsStreamData{yield}, yield);
} }
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
WsConnectionBuilder::connect(asio::yield_context yield) const WsConnectionBuilder::connect(asio::yield_context yield) const
{ {
auto sslConnection = sslConnect(yield); auto sslConnection = sslConnect(yield);
@@ -138,7 +138,7 @@ WsConnectionBuilder::connect(asio::yield_context yield) const
* @return WebSocket connection or error * @return WebSocket connection or error
*/ */
template <typename StreamDataType> template <typename StreamDataType>
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_context yield) const WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_context yield) const
{ {
auto context = asio::get_associated_executor(yield); auto context = asio::get_associated_executor(yield);
@@ -147,20 +147,20 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
asio::ip::tcp::resolver resolver(context); asio::ip::tcp::resolver resolver(context);
auto const results = resolver.async_resolve(host_, port_, yield[errorCode]); auto const results = resolver.async_resolve(host_, port_, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Resolve error", errorCode}}; return std::unexpected{RequestError{"Resolve error", errorCode}};
auto& ws = streamData.stream; auto& ws = streamData.stream;
beast::get_lowest_layer(ws).expires_after(connectionTimeout_); beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
auto endpoint = beast::get_lowest_layer(ws).async_connect(results, yield[errorCode]); auto endpoint = beast::get_lowest_layer(ws).async_connect(results, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Connect error", errorCode}}; return std::unexpected{RequestError{"Connect error", errorCode}};
if constexpr (StreamDataType::sslEnabled) { if constexpr (StreamDataType::sslEnabled) {
beast::get_lowest_layer(ws).expires_after(connectionTimeout_); beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
ws.next_layer().async_handshake(asio::ssl::stream_base::client, yield[errorCode]); ws.next_layer().async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"SSL handshake error", errorCode}}; return std::unexpected{RequestError{"SSL handshake error", errorCode}};
} }
// Turn off the timeout on the tcp_stream, because the websocket stream has its own timeout system // Turn off the timeout on the tcp_stream, because the websocket stream has its own timeout system
@@ -177,7 +177,7 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
std::string const host = fmt::format("{}:{}", host_, endpoint.port()); std::string const host = fmt::format("{}:{}", host_, endpoint.port());
ws.async_handshake(host, target_, yield[errorCode]); ws.async_handshake(host, target_, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Handshake error", errorCode}}; return std::unexpected{RequestError{"Handshake error", errorCode}};
if constexpr (StreamDataType::sslEnabled) { if constexpr (StreamDataType::sslEnabled) {
return std::make_unique<impl::SslWsConnection>(std::move(ws)); return std::make_unique<impl::SslWsConnection>(std::move(ws));

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/log/Logger.hpp" #include "util/log/Logger.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
@@ -32,6 +31,7 @@
#include <boost/beast/websocket/stream.hpp> #include <boost/beast/websocket/stream.hpp>
#include <chrono> #include <chrono>
#include <expected>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
@@ -55,7 +55,7 @@ public:
* @param yield yield context * @param yield yield context
* @return Message or error * @return Message or error
*/ */
virtual Expected<std::string, RequestError> virtual std::expected<std::string, RequestError>
read(boost::asio::yield_context yield) = 0; read(boost::asio::yield_context yield) = 0;
/** /**
@@ -154,7 +154,7 @@ public:
* @param yield yield context * @param yield yield context
* @return WebSocket connection or error * @return WebSocket connection or error
*/ */
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
sslConnect(boost::asio::yield_context yield) const; sslConnect(boost::asio::yield_context yield) const;
/** /**
@@ -163,7 +163,7 @@ public:
* @param yield yield context * @param yield yield context
* @return WebSocket connection or error * @return WebSocket connection or error
*/ */
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
plainConnect(boost::asio::yield_context yield) const; plainConnect(boost::asio::yield_context yield) const;
/** /**
@@ -172,14 +172,14 @@ public:
* @param yield yield context * @param yield yield context
* @return WebSocket connection or error * @return WebSocket connection or error
*/ */
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
connect(boost::asio::yield_context yield) const; connect(boost::asio::yield_context yield) const;
static constexpr std::chrono::seconds DEFAULT_TIMEOUT{5}; /**< Default timeout for connecting */ static constexpr std::chrono::seconds DEFAULT_TIMEOUT{5}; /**< Default timeout for connecting */
private: private:
template <typename StreamDataType> template <typename StreamDataType>
Expected<WsConnectionPtr, RequestError> std::expected<WsConnectionPtr, RequestError>
connectImpl(StreamDataType&& streamData, boost::asio::yield_context yield) const; connectImpl(StreamDataType&& streamData, boost::asio::yield_context yield) const;
}; };

View File

@@ -19,7 +19,6 @@
#include "util/requests/impl/SslContext.hpp" #include "util/requests/impl/SslContext.hpp"
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
@@ -33,6 +32,7 @@
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <expected>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <ios> #include <ios>
@@ -62,7 +62,7 @@ constexpr std::array CERT_FILE_PATHS{
"/system/etc/security/cacerts", // Android "/system/etc/security/cacerts", // Android
}; };
Expected<std::string, RequestError> std::expected<std::string, RequestError>
getRootCertificate() getRootCertificate()
{ {
for (auto const& path : CERT_FILE_PATHS) { for (auto const& path : CERT_FILE_PATHS) {
@@ -76,19 +76,19 @@ getRootCertificate()
return std::move(buffer).str(); return std::move(buffer).str();
} }
} }
return Unexpected{RequestError{"SSL setup failed: could not find root certificate"}}; return std::unexpected{RequestError{"SSL setup failed: could not find root certificate"}};
} }
} // namespace } // namespace
Expected<boost::asio::ssl::context, RequestError> std::expected<boost::asio::ssl::context, RequestError>
makeSslContext() makeSslContext()
{ {
ssl::context context{ssl::context::sslv23_client}; ssl::context context{ssl::context::sslv23_client};
context.set_verify_mode(ssl::verify_peer); context.set_verify_mode(ssl::verify_peer);
auto const rootCertificate = getRootCertificate(); auto const rootCertificate = getRootCertificate();
if (not rootCertificate.has_value()) { if (not rootCertificate.has_value()) {
return Unexpected{rootCertificate.error()}; return std::unexpected{rootCertificate.error()};
} }
context.add_certificate_authority(asio::buffer(rootCertificate->data(), rootCertificate->size())); context.add_certificate_authority(asio::buffer(rootCertificate->data(), rootCertificate->size()));
return context; return context;

View File

@@ -19,18 +19,18 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include <boost/asio/ssl/context.hpp> #include <boost/asio/ssl/context.hpp>
#include <boost/beast/core/error.hpp> #include <boost/beast/core/error.hpp>
#include <expected>
#include <optional> #include <optional>
#include <string> #include <string>
namespace util::requests::impl { namespace util::requests::impl {
Expected<boost::asio::ssl::context, RequestError> std::expected<boost::asio::ssl::context, RequestError>
makeSslContext(); makeSslContext();
std::optional<std::string> std::optional<std::string>

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include "util/requests/impl/SslContext.hpp" #include "util/requests/impl/SslContext.hpp"
@@ -33,6 +32,7 @@
#include <boost/beast/websocket.hpp> #include <boost/beast/websocket.hpp>
#include <boost/beast/websocket/stream.hpp> #include <boost/beast/websocket/stream.hpp>
#include <expected>
#include <utility> #include <utility>
namespace util::requests::impl { namespace util::requests::impl {
@@ -58,12 +58,12 @@ class SslStreamData {
public: public:
static constexpr bool sslEnabled = true; static constexpr bool sslEnabled = true;
static Expected<SslStreamData, RequestError> static std::expected<SslStreamData, RequestError>
create(boost::asio::yield_context yield) create(boost::asio::yield_context yield)
{ {
auto sslContext = makeSslContext(); auto sslContext = makeSslContext();
if (not sslContext.has_value()) { if (not sslContext.has_value()) {
return Unexpected{std::move(sslContext.error())}; return std::unexpected{std::move(sslContext.error())};
} }
return SslStreamData{std::move(sslContext).value(), yield}; return SslStreamData{std::move(sslContext).value(), yield};
} }

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include "util/requests/WsConnection.hpp" #include "util/requests/WsConnection.hpp"
@@ -35,6 +34,7 @@
#include <boost/beast/websocket/stream_base.hpp> #include <boost/beast/websocket/stream_base.hpp>
#include <chrono> #include <chrono>
#include <expected>
#include <optional> #include <optional>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -50,7 +50,7 @@ public:
{ {
} }
Expected<std::string, RequestError> std::expected<std::string, RequestError>
read(boost::asio::yield_context yield) override read(boost::asio::yield_context yield) override
{ {
boost::beast::error_code errorCode; boost::beast::error_code errorCode;
@@ -59,7 +59,7 @@ public:
ws_.async_read(buffer, yield[errorCode]); ws_.async_read(buffer, yield[errorCode]);
if (errorCode) if (errorCode)
return Unexpected{RequestError{"Read error", errorCode}}; return std::unexpected{RequestError{"Read error", errorCode}};
return boost::beast::buffers_to_string(std::move(buffer).data()); return boost::beast::buffers_to_string(std::move(buffer).data());
} }

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/MockOperation.hpp" #include "util/MockOperation.hpp"
#include "util/MockStopToken.hpp" #include "util/MockStopToken.hpp"
#include "util/MockStrand.hpp" #include "util/MockStrand.hpp"
@@ -30,12 +29,13 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <chrono> #include <chrono>
#include <expected>
#include <functional> #include <functional>
#include <optional> #include <optional>
struct MockExecutionContext { struct MockExecutionContext {
template <typename T> template <typename T>
using ValueType = util::Expected<T, util::async::ExecutionError>; using ValueType = std::expected<T, util::async::ExecutionError>;
using StopSource = MockStopSource; using StopSource = MockStopSource;
using StopToken = MockStopToken; using StopToken = MockStopToken;

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/MockOperation.hpp" #include "util/MockOperation.hpp"
#include "util/async/AnyStopToken.hpp" #include "util/async/AnyStopToken.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
@@ -28,12 +27,13 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <chrono> #include <chrono>
#include <expected>
#include <functional> #include <functional>
#include <optional> #include <optional>
struct MockStrand { struct MockStrand {
template <typename T> template <typename T>
using ValueType = util::Expected<T, util::async::ExecutionError>; using ValueType = std::expected<T, util::async::ExecutionError>;
template <typename T> template <typename T>
using Operation = MockOperation<T>; using Operation = MockOperation<T>;

View File

@@ -19,7 +19,6 @@
#include "util/TestWsServer.hpp" #include "util/TestWsServer.hpp"
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
@@ -38,6 +37,7 @@
#include <boost/beast/websocket/stream_base.hpp> #include <boost/beast/websocket/stream_base.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <expected>
#include <optional> #include <optional>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -91,7 +91,7 @@ TestWsServer::TestWsServer(asio::io_context& context, std::string const& host, i
acceptor_.bind(endpoint); acceptor_.bind(endpoint);
} }
util::Expected<TestWsConnection, util::requests::RequestError> std::expected<TestWsConnection, util::requests::RequestError>
TestWsServer::acceptConnection(asio::yield_context yield) TestWsServer::acceptConnection(asio::yield_context yield)
{ {
acceptor_.listen(asio::socket_base::max_listen_connections); acceptor_.listen(asio::socket_base::max_listen_connections);
@@ -100,13 +100,13 @@ TestWsServer::acceptConnection(asio::yield_context yield)
asio::ip::tcp::socket socket(acceptor_.get_executor()); asio::ip::tcp::socket socket(acceptor_.get_executor());
acceptor_.async_accept(socket, yield[errorCode]); acceptor_.async_accept(socket, yield[errorCode]);
if (errorCode) if (errorCode)
return util::Unexpected{util::requests::RequestError{"Accept error", errorCode}}; return std::unexpected{util::requests::RequestError{"Accept error", errorCode}};
boost::beast::websocket::stream<boost::beast::tcp_stream> ws(std::move(socket)); boost::beast::websocket::stream<boost::beast::tcp_stream> ws(std::move(socket));
ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server)); ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
ws.async_accept(yield[errorCode]); ws.async_accept(yield[errorCode]);
if (errorCode) if (errorCode)
return util::Unexpected{util::requests::RequestError{"Handshake error", errorCode}}; return std::unexpected{util::requests::RequestError{"Handshake error", errorCode}};
return TestWsConnection(std::move(ws)); return TestWsConnection(std::move(ws));
} }

View File

@@ -19,7 +19,6 @@
#pragma once #pragma once
#include "util/Expected.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
@@ -28,6 +27,7 @@
#include <boost/beast/core/tcp_stream.hpp> #include <boost/beast/core/tcp_stream.hpp>
#include <boost/beast/websocket/stream.hpp> #include <boost/beast/websocket/stream.hpp>
#include <expected>
#include <functional> #include <functional>
#include <optional> #include <optional>
#include <string> #include <string>
@@ -59,7 +59,7 @@ class TestWsServer {
public: public:
TestWsServer(boost::asio::io_context& context, std::string const& host, int port); TestWsServer(boost::asio::io_context& context, std::string const& host, int port);
util::Expected<TestWsConnection, util::requests::RequestError> std::expected<TestWsConnection, util::requests::RequestError>
acceptConnection(boost::asio::yield_context yield); acceptConnection(boost::asio::yield_context yield);
void void

View File

@@ -17,7 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include "util/Expected.hpp"
#include "util/MockOperation.hpp" #include "util/MockOperation.hpp"
#include "util/async/AnyOperation.hpp" #include "util/async/AnyOperation.hpp"
#include "util/async/Error.hpp" #include "util/async/Error.hpp"
@@ -26,14 +25,15 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <any> #include <any>
#include <expected>
#include <string> #include <string>
using namespace util::async; using namespace util::async;
using namespace ::testing; using namespace ::testing;
struct AnyOperationTests : Test { struct AnyOperationTests : Test {
using OperationType = MockOperation<util::Expected<impl::Any, ExecutionError>>; using OperationType = MockOperation<std::expected<impl::Any, ExecutionError>>;
using ScheduledOperationType = MockScheduledOperation<util::Expected<impl::Any, ExecutionError>>; using ScheduledOperationType = MockScheduledOperation<std::expected<impl::Any, ExecutionError>>;
NaggyMock<OperationType> mockOp; NaggyMock<OperationType> mockOp;
NaggyMock<ScheduledOperationType> mockScheduledOp; NaggyMock<ScheduledOperationType> mockScheduledOp;
@@ -46,7 +46,7 @@ using AnyOperationDeathTest = AnyOperationTests;
TEST_F(AnyOperationTests, VoidDataYieldsNoError) TEST_F(AnyOperationTests, VoidDataYieldsNoError)
{ {
auto const noError = util::Expected<impl::Any, ExecutionError>(impl::Any{}); auto const noError = std::expected<impl::Any, ExecutionError>(impl::Any{});
EXPECT_CALL(mockOp, get()).WillOnce(Return(noError)); EXPECT_CALL(mockOp, get()).WillOnce(Return(noError));
auto res = voidOp.get(); auto res = voidOp.get();
ASSERT_TRUE(res); ASSERT_TRUE(res);
@@ -85,7 +85,7 @@ TEST_F(AnyOperationTests, RequestStopCallPropagated)
TEST_F(AnyOperationTests, GetPropagatesError) TEST_F(AnyOperationTests, GetPropagatesError)
{ {
EXPECT_CALL(mockOp, get()).WillOnce(Return(util::Unexpected(ExecutionError{"tid", "Not good"}))); EXPECT_CALL(mockOp, get()).WillOnce(Return(std::unexpected(ExecutionError{"tid", "Not good"})));
auto res = intOp.get(); auto res = intOp.get();
ASSERT_FALSE(res); ASSERT_FALSE(res);
EXPECT_TRUE(res.error().message.ends_with("Not good")); EXPECT_TRUE(res.error().message.ends_with("Not good"));

View File

@@ -17,7 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include "util/Expected.hpp"
#include "util/MockOperation.hpp" #include "util/MockOperation.hpp"
#include "util/MockStrand.hpp" #include "util/MockStrand.hpp"
#include "util/async/AnyOperation.hpp" #include "util/async/AnyOperation.hpp"
@@ -29,6 +28,7 @@
#include <any> #include <any>
#include <chrono> #include <chrono>
#include <expected>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>

View File

@@ -17,7 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include "util/Expected.hpp"
#include "util/Fixtures.hpp" #include "util/Fixtures.hpp"
#include "util/TestHttpServer.hpp" #include "util/TestHttpServer.hpp"
#include "util/requests/RequestBuilder.hpp" #include "util/requests/RequestBuilder.hpp"
@@ -32,6 +31,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <chrono> #include <chrono>
#include <expected>
#include <optional> #include <optional>
#include <string> #include <string>
#include <thread> #include <thread>
@@ -111,14 +111,14 @@ TEST_P(RequestBuilderTest, SimpleRequest)
); );
runSpawn([this, replyBody](asio::yield_context yield) { runSpawn([this, replyBody](asio::yield_context yield) {
auto const response = [&]() -> util::Expected<std::string, RequestError> { auto const response = [&]() -> std::expected<std::string, RequestError> {
switch (GetParam().method) { switch (GetParam().method) {
case http::verb::get: case http::verb::get:
return builder.getPlain(yield); return builder.getPlain(yield);
case http::verb::post: case http::verb::post:
return builder.postPlain(yield); return builder.postPlain(yield);
default: default:
return util::Unexpected{RequestError{"Invalid HTTP verb"}}; return std::unexpected{RequestError{"Invalid HTTP verb"}};
} }
}(); }();
ASSERT_TRUE(response) << response.error().message(); ASSERT_TRUE(response) << response.error().message();
@@ -243,14 +243,14 @@ TEST_P(RequestBuilderSslTest, TrySslUsePlain)
); );
runSpawn([this](asio::yield_context yield) { runSpawn([this](asio::yield_context yield) {
auto const response = [&]() -> util::Expected<std::string, RequestError> { auto const response = [&]() -> std::expected<std::string, RequestError> {
switch (GetParam().method) { switch (GetParam().method) {
case http::verb::get: case http::verb::get:
return builder.get(yield); return builder.get(yield);
case http::verb::post: case http::verb::post:
return builder.post(yield); return builder.post(yield);
default: default:
return util::Unexpected{RequestError{"Invalid HTTP verb"}}; return std::unexpected{RequestError{"Invalid HTTP verb"}};
} }
}(); }();
ASSERT_TRUE(response) << response.error().message(); ASSERT_TRUE(response) << response.error().message();

View File

@@ -17,7 +17,6 @@
*/ */
//============================================================================== //==============================================================================
#include "util/Expected.hpp"
#include "util/Fixtures.hpp" #include "util/Fixtures.hpp"
#include "util/TestWsServer.hpp" #include "util/TestWsServer.hpp"
#include "util/requests/Types.hpp" #include "util/requests/Types.hpp"
@@ -29,6 +28,7 @@
#include <chrono> #include <chrono>
#include <cstddef> #include <cstddef>
#include <expected>
#include <optional> #include <optional>
#include <string> #include <string>
#include <thread> #include <thread>
@@ -44,7 +44,7 @@ struct WsConnectionTestsBase : SyncAsioContextTest {
template <typename T, typename E> template <typename T, typename E>
T T
unwrap(util::Expected<T, E> expected) unwrap(std::expected<T, E> expected)
{ {
[&]() { ASSERT_TRUE(expected.has_value()) << expected.error().message(); }(); [&]() { ASSERT_TRUE(expected.has_value()) << expected.error().message(); }();
return std::move(expected).value(); return std::move(expected).value();