mirror of
				https://github.com/XRPLF/clio.git
				synced 2025-11-04 11:55:51 +00:00 
			
		
		
		
	
							
								
								
									
										3
									
								
								.clangd
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								.clangd
									
									
									
									
									
								
							@@ -1,3 +1,6 @@
 | 
			
		||||
CompileFlags:
 | 
			
		||||
  Add: [-D__cpp_concepts=202002]
 | 
			
		||||
 | 
			
		||||
Diagnostics:
 | 
			
		||||
  UnusedIncludes: Strict
 | 
			
		||||
  MissingIncludes: Strict
 | 
			
		||||
 
 | 
			
		||||
@@ -19,9 +19,8 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <expected>
 | 
			
		||||
 | 
			
		||||
namespace data::cassandra {
 | 
			
		||||
 | 
			
		||||
@@ -59,8 +58,8 @@ struct Limit {
 | 
			
		||||
class Handle;
 | 
			
		||||
class CassandraError;
 | 
			
		||||
 | 
			
		||||
using MaybeError = util::Expected<void, CassandraError>;
 | 
			
		||||
using ResultOrError = util::Expected<Result, CassandraError>;
 | 
			
		||||
using Error = util::Unexpected<CassandraError>;
 | 
			
		||||
using MaybeError = std::expected<void, CassandraError>;
 | 
			
		||||
using ResultOrError = std::expected<Result, CassandraError>;
 | 
			
		||||
using Error = std::unexpected<CassandraError>;
 | 
			
		||||
 | 
			
		||||
}  // namespace data::cassandra
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,10 @@
 | 
			
		||||
#include "data/cassandra/Types.hpp"
 | 
			
		||||
#include "data/cassandra/impl/ManagedObject.hpp"
 | 
			
		||||
#include "data/cassandra/impl/Statement.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
 | 
			
		||||
#include <cassandra.h>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@
 | 
			
		||||
#include "etl/impl/SubscriptionSource.hpp"
 | 
			
		||||
 | 
			
		||||
#include "rpc/JS.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/Retry.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
@@ -42,6 +41,7 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <future>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,6 @@
 | 
			
		||||
#include "rpc/Errors.hpp"
 | 
			
		||||
#include "rpc/common/APIVersion.hpp"
 | 
			
		||||
#include "rpc/common/Types.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/Taggable.hpp"
 | 
			
		||||
#include "web/Context.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +33,7 @@
 | 
			
		||||
#include <boost/json/value_to.hpp>
 | 
			
		||||
#include <ripple/protocol/ErrorCodes.h>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
@@ -43,7 +43,7 @@ using namespace util;
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
util::Expected<web::Context, Status>
 | 
			
		||||
std::expected<web::Context, Status>
 | 
			
		||||
make_WsContext(
 | 
			
		||||
    boost::asio::yield_context yc,
 | 
			
		||||
    boost::json::object const& request,
 | 
			
		||||
@@ -72,7 +72,7 @@ make_WsContext(
 | 
			
		||||
    return web::Context(yc, command, *apiVersion, request, session, tagFactory, range, clientIp, session->isAdmin());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<web::Context, Status>
 | 
			
		||||
std::expected<web::Context, Status>
 | 
			
		||||
make_HttpContext(
 | 
			
		||||
    boost::asio::yield_context yc,
 | 
			
		||||
    boost::json::object const& request,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@
 | 
			
		||||
#include "data/Types.hpp"
 | 
			
		||||
#include "rpc/Errors.hpp"
 | 
			
		||||
#include "rpc/common/APIVersion.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/Taggable.hpp"
 | 
			
		||||
#include "web/Context.hpp"
 | 
			
		||||
#include "web/interface/ConnectionBase.hpp"
 | 
			
		||||
@@ -31,6 +30,7 @@
 | 
			
		||||
#include <boost/json.hpp>
 | 
			
		||||
#include <boost/json/object.hpp>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
@@ -56,7 +56,7 @@ namespace rpc {
 | 
			
		||||
 * @param apiVersionParser A parser that is used to parse out the "api_version" field
 | 
			
		||||
 * @return A Websocket context or error Status
 | 
			
		||||
 */
 | 
			
		||||
util::Expected<web::Context, Status>
 | 
			
		||||
std::expected<web::Context, Status>
 | 
			
		||||
make_WsContext(
 | 
			
		||||
    boost::asio::yield_context yc,
 | 
			
		||||
    boost::json::object const& request,
 | 
			
		||||
@@ -79,7 +79,7 @@ make_WsContext(
 | 
			
		||||
 * @param isAdmin Whether the connection has admin privileges
 | 
			
		||||
 * @return A HTTP context or error Status
 | 
			
		||||
 */
 | 
			
		||||
util::Expected<web::Context, Status>
 | 
			
		||||
std::expected<web::Context, Status>
 | 
			
		||||
make_HttpContext(
 | 
			
		||||
    boost::asio::yield_context yc,
 | 
			
		||||
    boost::json::object const& request,
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@
 | 
			
		||||
#include <ripple/protocol/STObject.h>
 | 
			
		||||
#include <ripple/protocol/STTx.h>
 | 
			
		||||
#include <ripple/protocol/SecretKey.h>
 | 
			
		||||
#include <ripple/protocol/Seed.h>
 | 
			
		||||
#include <ripple/protocol/TxMeta.h>
 | 
			
		||||
#include <ripple/protocol/UintTypes.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,13 +19,11 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/json.hpp>
 | 
			
		||||
#include <boost/json/object.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <expected>
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
@@ -60,7 +58,7 @@ public:
 | 
			
		||||
     * @param request A JSON object representing the request
 | 
			
		||||
     * @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
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,8 @@
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
struct RpcSpec;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @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) {
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -103,4 +103,9 @@ private:
 | 
			
		||||
    std::vector<FieldSpec> fields_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief An alias for a const reference to @ref RpcSpec.
 | 
			
		||||
 */
 | 
			
		||||
using RpcSpecConstRef = RpcSpec const&;
 | 
			
		||||
 | 
			
		||||
}  // namespace rpc
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "rpc/Errors.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/spawn.hpp>
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
@@ -31,6 +30,7 @@
 | 
			
		||||
#include <ripple/basics/strHex.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <variant>
 | 
			
		||||
@@ -48,35 +48,28 @@ class SubscriptionManager;
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
class Counters;
 | 
			
		||||
struct RpcSpec;
 | 
			
		||||
struct FieldSpec;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return type used for Validators that can return error but don't have
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
using Error = util::Unexpected<Status>;
 | 
			
		||||
using Error = std::unexpected<Status>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return type for each individual handler
 | 
			
		||||
 */
 | 
			
		||||
template <typename OutputType>
 | 
			
		||||
using HandlerReturnType = util::Expected<OutputType, Status>;
 | 
			
		||||
using HandlerReturnType = std::expected<OutputType, Status>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The final return type out of RPC engine
 | 
			
		||||
 */
 | 
			
		||||
using ReturnType = util::Expected<boost::json::value, Status>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief An alias for a const reference to @ref RpcSpec.
 | 
			
		||||
 */
 | 
			
		||||
using RpcSpecConstRef = RpcSpec const&;
 | 
			
		||||
using ReturnType = std::expected<boost::json::value, Status>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief An empty type used as Output for handlers than don't actually produce output.
 | 
			
		||||
 
 | 
			
		||||
@@ -20,13 +20,13 @@
 | 
			
		||||
#include "rpc/common/impl/APIVersionParser.hpp"
 | 
			
		||||
 | 
			
		||||
#include "rpc/common/APIVersion.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/object.hpp>
 | 
			
		||||
#include <fmt/core.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
{
 | 
			
		||||
    using Error = util::Unexpected<std::string>;
 | 
			
		||||
    using Error = std::unexpected<std::string>;
 | 
			
		||||
 | 
			
		||||
    if (request.contains("api_version")) {
 | 
			
		||||
        if (!request.at("api_version").is_int64())
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "rpc/common/APIVersion.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/config/Config.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +27,7 @@
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace rpc::impl {
 | 
			
		||||
@@ -74,7 +74,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    inline uint32_t
 | 
			
		||||
 
 | 
			
		||||
@@ -112,7 +112,7 @@ ProductionHandlerProvider::ProductionHandlerProvider(
 | 
			
		||||
bool
 | 
			
		||||
ProductionHandlerProvider::contains(std::string const& command) const
 | 
			
		||||
{
 | 
			
		||||
    return handlerMap_.contains(command);  // updated on 4 mar 2024
 | 
			
		||||
    return handlerMap_.contains(command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<AnyHandler>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "rpc/common/Concepts.hpp"
 | 
			
		||||
#include "rpc/common/Specs.hpp"
 | 
			
		||||
#include "rpc/common/Types.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/value.hpp>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,6 @@
 | 
			
		||||
#include "rpc/JS.hpp"
 | 
			
		||||
#include "rpc/RPCHelpers.hpp"
 | 
			
		||||
#include "rpc/common/MetaProcessors.hpp"
 | 
			
		||||
#include "rpc/common/Specs.hpp"
 | 
			
		||||
#include "rpc/common/Types.hpp"
 | 
			
		||||
#include "rpc/common/Validators.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/array.hpp>
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "data/BackendInterface.hpp"
 | 
			
		||||
#include "rpc/common/Types.hpp"
 | 
			
		||||
#include "rpc/common/Specs.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/array.hpp>
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/async/Concepts.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
#include "util/async/impl/Any.hpp"
 | 
			
		||||
@@ -29,6 +28,7 @@
 | 
			
		||||
#include <fmt/std.h>
 | 
			
		||||
 | 
			
		||||
#include <any>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -95,13 +95,13 @@ public:
 | 
			
		||||
     *
 | 
			
		||||
     * @return The result of the operation
 | 
			
		||||
     */
 | 
			
		||||
    [[nodiscard]] util::Expected<RetType, ExecutionError>
 | 
			
		||||
    [[nodiscard]] std::expected<RetType, ExecutionError>
 | 
			
		||||
    get()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            auto data = operation_.get();
 | 
			
		||||
            if (not data)
 | 
			
		||||
                return util::Unexpected(std::move(data).error());
 | 
			
		||||
                return std::unexpected(std::move(data).error());
 | 
			
		||||
 | 
			
		||||
            if constexpr (std::is_void_v<RetType>) {
 | 
			
		||||
                return {};
 | 
			
		||||
@@ -110,7 +110,7 @@ public:
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } 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")};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/async/Concepts.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
#include "util/async/Operation.hpp"
 | 
			
		||||
@@ -38,6 +37,7 @@
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -82,9 +82,9 @@ struct AsioPoolContext {
 | 
			
		||||
 * @brief A highly configurable execution context.
 | 
			
		||||
 *
 | 
			
		||||
 * 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
 | 
			
		||||
 * package them as the error channel of util::Expected.
 | 
			
		||||
 * package them as the error channel of std::expected.
 | 
			
		||||
 */
 | 
			
		||||
template <
 | 
			
		||||
    typename ContextType,
 | 
			
		||||
@@ -108,7 +108,7 @@ public:
 | 
			
		||||
    using ExecutorType = typename ContextHolderType::Executor;
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    using ValueType = util::Expected<T, ExecutionError>;
 | 
			
		||||
    using ValueType = std::expected<T, ExecutionError>;
 | 
			
		||||
 | 
			
		||||
    using StopSource = StopSourceType;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/async/Concepts.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
#include "util/async/context/impl/Timer.hpp"
 | 
			
		||||
@@ -28,6 +27,7 @@
 | 
			
		||||
#include <boost/asio/strand.hpp>
 | 
			
		||||
#include <boost/asio/thread_pool.hpp>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
namespace util::async::impl {
 | 
			
		||||
@@ -62,12 +62,12 @@ outcomeForHandler(auto&& fn)
 | 
			
		||||
{
 | 
			
		||||
    if constexpr (SomeHandlerWith<decltype(fn), 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>();
 | 
			
		||||
    } else {
 | 
			
		||||
        using FnRetType = decltype(fn());
 | 
			
		||||
        using RetType = util::Expected<FnRetType, ExecutionError>;
 | 
			
		||||
        using RetType = std::expected<FnRetType, ExecutionError>;
 | 
			
		||||
 | 
			
		||||
        return Outcome<RetType>();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,8 @@
 | 
			
		||||
#include <any>
 | 
			
		||||
#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)
 | 
			
		||||
// Issue to track this removal can be found here: https://github.com/XRPLF/clio/issues/1174
 | 
			
		||||
 | 
			
		||||
namespace util::async::impl {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Assert.hpp"
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/async/Concepts.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
#include "util/async/impl/Any.hpp"
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ public:
 | 
			
		||||
        pimpl_->wait();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    util::Expected<Any, ExecutionError>
 | 
			
		||||
    std::expected<Any, ExecutionError>
 | 
			
		||||
    get()
 | 
			
		||||
    {
 | 
			
		||||
        return pimpl_->get();
 | 
			
		||||
@@ -87,7 +87,7 @@ private:
 | 
			
		||||
 | 
			
		||||
        virtual void
 | 
			
		||||
        wait() noexcept = 0;
 | 
			
		||||
        virtual util::Expected<Any, ExecutionError>
 | 
			
		||||
        virtual std::expected<Any, ExecutionError>
 | 
			
		||||
        get() = 0;
 | 
			
		||||
        virtual void
 | 
			
		||||
        requestStop() = 0;
 | 
			
		||||
@@ -111,7 +111,7 @@ private:
 | 
			
		||||
            return operation.wait();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        util::Expected<Any, ExecutionError>
 | 
			
		||||
        std::expected<Any, ExecutionError>
 | 
			
		||||
        get() override
 | 
			
		||||
        {
 | 
			
		||||
            // Note: return type of the operation was already wrapped to impl::Any by AnyExecutionContext
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/async/Concepts.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -27,6 +26,7 @@
 | 
			
		||||
#include <fmt/std.h>
 | 
			
		||||
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
namespace util::async::impl {
 | 
			
		||||
@@ -41,11 +41,11 @@ struct DefaultErrorHandler {
 | 
			
		||||
                    fn(outcome, std::forward<Args>(args)...);
 | 
			
		||||
                } catch (std::exception const& e) {
 | 
			
		||||
                    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 (...) {
 | 
			
		||||
                    outcome.setValue(
 | 
			
		||||
                        util::Unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"})
 | 
			
		||||
                        std::unexpected(ExecutionError{fmt::format("{}", std::this_thread::get_id()), "unknown"})
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#include "util/requests/RequestBuilder.hpp"
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
#include "util/requests/impl/StreamData.hpp"
 | 
			
		||||
@@ -41,6 +40,7 @@
 | 
			
		||||
#include <openssl/tls1.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <string_view>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -97,48 +97,48 @@ RequestBuilder::setTarget(std::string_view target)
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::getSsl(boost::asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    return doSslRequest(yield, http::verb::get);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::getPlain(boost::asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    return doPlainRequest(yield, http::verb::get);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::get(asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    return doRequest(yield, http::verb::get);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::postSsl(boost::asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    return doSslRequest(yield, http::verb::post);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::postPlain(boost::asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    return doPlainRequest(yield, http::verb::post);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::post(asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    auto streamData = impl::SslTcpStreamData::create(yield);
 | 
			
		||||
    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 ignored "-Wold-style-cast"
 | 
			
		||||
@@ -146,19 +146,19 @@ RequestBuilder::doSslRequest(asio::yield_context yield, beast::http::verb method
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
        beast::error_code errorCode;
 | 
			
		||||
        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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::doPlainRequest(asio::yield_context yield, beast::http::verb method)
 | 
			
		||||
{
 | 
			
		||||
    auto streamData = impl::TcpStreamData{yield};
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    auto result = doSslRequest(yield, method);
 | 
			
		||||
@@ -179,7 +179,7 @@ RequestBuilder::doRequest(asio::yield_context yield, beast::http::verb method)
 | 
			
		||||
 * @return Response or error
 | 
			
		||||
 */
 | 
			
		||||
template <typename StreamDataType>
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context yield, http::verb const method)
 | 
			
		||||
{
 | 
			
		||||
    auto executor = asio::get_associated_executor(yield);
 | 
			
		||||
@@ -188,14 +188,14 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
 | 
			
		||||
    tcp::resolver resolver(executor);
 | 
			
		||||
    auto const resolverResult = resolver.async_resolve(host_, port_, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Resolve error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Resolve error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    auto& stream = streamData.stream;
 | 
			
		||||
 | 
			
		||||
    beast::get_lowest_layer(stream).expires_after(timeout_);
 | 
			
		||||
    beast::get_lowest_layer(stream).async_connect(resolverResult, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Connection error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Connection error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    request_.method(method);
 | 
			
		||||
 | 
			
		||||
@@ -203,28 +203,28 @@ RequestBuilder::doRequestImpl(StreamDataType&& streamData, asio::yield_context y
 | 
			
		||||
        beast::get_lowest_layer(stream).expires_after(timeout_);
 | 
			
		||||
        stream.async_handshake(asio::ssl::stream_base::client, yield[errorCode]);
 | 
			
		||||
        if (errorCode)
 | 
			
		||||
            return Unexpected{RequestError{"Handshake error", errorCode}};
 | 
			
		||||
            return std::unexpected{RequestError{"Handshake error", errorCode}};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    beast::get_lowest_layer(stream).expires_after(timeout_);
 | 
			
		||||
    http::async_write(stream, request_, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Write error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Write error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    beast::flat_buffer buffer;
 | 
			
		||||
    http::response<http::string_body> response;
 | 
			
		||||
 | 
			
		||||
    http::async_read(stream, buffer, response, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Read error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Read error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +32,7 @@
 | 
			
		||||
#include <boost/beast/http/verb.hpp>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <string_view>
 | 
			
		||||
#include <vector>
 | 
			
		||||
@@ -116,7 +116,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    getSsl(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -128,7 +128,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    getPlain(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -141,7 +141,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    get(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -153,7 +153,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    postSsl(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -165,7 +165,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    postPlain(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -178,23 +178,23 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Expected response or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    post(boost::asio::yield_context yield);
 | 
			
		||||
 | 
			
		||||
    static constexpr std::chrono::milliseconds DEFAULT_TIMEOUT{30000}; /**< Default timeout for requests */
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    doRequest(boost::asio::yield_context yield, boost::beast::http::verb method);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#include "util/requests/WsConnection.hpp"
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
#include "util/requests/impl/StreamData.hpp"
 | 
			
		||||
@@ -41,6 +40,7 @@
 | 
			
		||||
#include <openssl/tls1.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -92,12 +92,12 @@ WsConnectionBuilder::setWsHandshakeTimeout(std::chrono::steady_clock::duration t
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
WsConnectionBuilder::sslConnect(asio::yield_context yield) const
 | 
			
		||||
{
 | 
			
		||||
    auto streamData = impl::SslWsStreamData::create(yield);
 | 
			
		||||
    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 ignored "-Wold-style-cast"
 | 
			
		||||
@@ -105,18 +105,18 @@ WsConnectionBuilder::sslConnect(asio::yield_context yield) const
 | 
			
		||||
#pragma GCC diagnostic pop
 | 
			
		||||
        beast::error_code errorCode;
 | 
			
		||||
        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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
WsConnectionBuilder::plainConnect(asio::yield_context yield) const
 | 
			
		||||
{
 | 
			
		||||
    return connectImpl(impl::WsStreamData{yield}, yield);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
WsConnectionBuilder::connect(asio::yield_context yield) const
 | 
			
		||||
{
 | 
			
		||||
    auto sslConnection = sslConnect(yield);
 | 
			
		||||
@@ -138,7 +138,7 @@ WsConnectionBuilder::connect(asio::yield_context yield) const
 | 
			
		||||
 * @return WebSocket connection or error
 | 
			
		||||
 */
 | 
			
		||||
template <typename StreamDataType>
 | 
			
		||||
Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_context yield) const
 | 
			
		||||
{
 | 
			
		||||
    auto context = asio::get_associated_executor(yield);
 | 
			
		||||
@@ -147,20 +147,20 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
 | 
			
		||||
    asio::ip::tcp::resolver resolver(context);
 | 
			
		||||
    auto const results = resolver.async_resolve(host_, port_, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Resolve error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Resolve error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    auto& ws = streamData.stream;
 | 
			
		||||
 | 
			
		||||
    beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
 | 
			
		||||
    auto endpoint = beast::get_lowest_layer(ws).async_connect(results, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Connect error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Connect error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    if constexpr (StreamDataType::sslEnabled) {
 | 
			
		||||
        beast::get_lowest_layer(ws).expires_after(connectionTimeout_);
 | 
			
		||||
        ws.next_layer().async_handshake(asio::ssl::stream_base::client, yield[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
 | 
			
		||||
@@ -177,7 +177,7 @@ WsConnectionBuilder::connectImpl(StreamDataType&& streamData, asio::yield_contex
 | 
			
		||||
    std::string const host = fmt::format("{}:{}", host_, endpoint.port());
 | 
			
		||||
    ws.async_handshake(host, target_, yield[errorCode]);
 | 
			
		||||
    if (errorCode)
 | 
			
		||||
        return Unexpected{RequestError{"Handshake error", errorCode}};
 | 
			
		||||
        return std::unexpected{RequestError{"Handshake error", errorCode}};
 | 
			
		||||
 | 
			
		||||
    if constexpr (StreamDataType::sslEnabled) {
 | 
			
		||||
        return std::make_unique<impl::SslWsConnection>(std::move(ws));
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/log/Logger.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -32,6 +31,7 @@
 | 
			
		||||
#include <boost/beast/websocket/stream.hpp>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
@@ -55,7 +55,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return Message or error
 | 
			
		||||
     */
 | 
			
		||||
    virtual Expected<std::string, RequestError>
 | 
			
		||||
    virtual std::expected<std::string, RequestError>
 | 
			
		||||
    read(boost::asio::yield_context yield) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -154,7 +154,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return WebSocket connection or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    sslConnect(boost::asio::yield_context yield) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -163,7 +163,7 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return WebSocket connection or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    plainConnect(boost::asio::yield_context yield) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -172,14 +172,14 @@ public:
 | 
			
		||||
     * @param yield yield context
 | 
			
		||||
     * @return WebSocket connection or error
 | 
			
		||||
     */
 | 
			
		||||
    Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    connect(boost::asio::yield_context yield) const;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::chrono::seconds DEFAULT_TIMEOUT{5}; /**< Default timeout for connecting */
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    template <typename StreamDataType>
 | 
			
		||||
    Expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    std::expected<WsConnectionPtr, RequestError>
 | 
			
		||||
    connectImpl(StreamDataType&& streamData, boost::asio::yield_context yield) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#include "util/requests/impl/SslContext.hpp"
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/buffer.hpp>
 | 
			
		||||
@@ -33,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <ios>
 | 
			
		||||
@@ -62,7 +62,7 @@ constexpr std::array CERT_FILE_PATHS{
 | 
			
		||||
    "/system/etc/security/cacerts",                       // Android
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Expected<std::string, RequestError>
 | 
			
		||||
std::expected<std::string, RequestError>
 | 
			
		||||
getRootCertificate()
 | 
			
		||||
{
 | 
			
		||||
    for (auto const& path : CERT_FILE_PATHS) {
 | 
			
		||||
@@ -76,19 +76,19 @@ getRootCertificate()
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
Expected<boost::asio::ssl::context, RequestError>
 | 
			
		||||
std::expected<boost::asio::ssl::context, RequestError>
 | 
			
		||||
makeSslContext()
 | 
			
		||||
{
 | 
			
		||||
    ssl::context context{ssl::context::sslv23_client};
 | 
			
		||||
    context.set_verify_mode(ssl::verify_peer);
 | 
			
		||||
    auto const rootCertificate = getRootCertificate();
 | 
			
		||||
    if (not rootCertificate.has_value()) {
 | 
			
		||||
        return Unexpected{rootCertificate.error()};
 | 
			
		||||
        return std::unexpected{rootCertificate.error()};
 | 
			
		||||
    }
 | 
			
		||||
    context.add_certificate_authority(asio::buffer(rootCertificate->data(), rootCertificate->size()));
 | 
			
		||||
    return context;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,18 +19,18 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/ssl/context.hpp>
 | 
			
		||||
#include <boost/beast/core/error.hpp>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace util::requests::impl {
 | 
			
		||||
 | 
			
		||||
Expected<boost::asio::ssl::context, RequestError>
 | 
			
		||||
std::expected<boost::asio::ssl::context, RequestError>
 | 
			
		||||
makeSslContext();
 | 
			
		||||
 | 
			
		||||
std::optional<std::string>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
#include "util/requests/impl/SslContext.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +32,7 @@
 | 
			
		||||
#include <boost/beast/websocket.hpp>
 | 
			
		||||
#include <boost/beast/websocket/stream.hpp>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace util::requests::impl {
 | 
			
		||||
@@ -58,12 +58,12 @@ class SslStreamData {
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr bool sslEnabled = true;
 | 
			
		||||
 | 
			
		||||
    static Expected<SslStreamData, RequestError>
 | 
			
		||||
    static std::expected<SslStreamData, RequestError>
 | 
			
		||||
    create(boost::asio::yield_context yield)
 | 
			
		||||
    {
 | 
			
		||||
        auto sslContext = makeSslContext();
 | 
			
		||||
        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};
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
#include "util/requests/WsConnection.hpp"
 | 
			
		||||
 | 
			
		||||
@@ -35,6 +34,7 @@
 | 
			
		||||
#include <boost/beast/websocket/stream_base.hpp>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -50,7 +50,7 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Expected<std::string, RequestError>
 | 
			
		||||
    std::expected<std::string, RequestError>
 | 
			
		||||
    read(boost::asio::yield_context yield) override
 | 
			
		||||
    {
 | 
			
		||||
        boost::beast::error_code errorCode;
 | 
			
		||||
@@ -59,7 +59,7 @@ public:
 | 
			
		||||
        ws_.async_read(buffer, yield[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());
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/MockOperation.hpp"
 | 
			
		||||
#include "util/MockStopToken.hpp"
 | 
			
		||||
#include "util/MockStrand.hpp"
 | 
			
		||||
@@ -30,12 +29,13 @@
 | 
			
		||||
#include <gmock/gmock.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
struct MockExecutionContext {
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    using ValueType = util::Expected<T, util::async::ExecutionError>;
 | 
			
		||||
    using ValueType = std::expected<T, util::async::ExecutionError>;
 | 
			
		||||
 | 
			
		||||
    using StopSource = MockStopSource;
 | 
			
		||||
    using StopToken = MockStopToken;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/MockOperation.hpp"
 | 
			
		||||
#include "util/async/AnyStopToken.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
@@ -28,12 +27,13 @@
 | 
			
		||||
#include <gmock/gmock.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <optional>
 | 
			
		||||
 | 
			
		||||
struct MockStrand {
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    using ValueType = util::Expected<T, util::async::ExecutionError>;
 | 
			
		||||
    using ValueType = std::expected<T, util::async::ExecutionError>;
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    using Operation = MockOperation<T>;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#include "util/TestWsServer.hpp"
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/buffer.hpp>
 | 
			
		||||
@@ -38,6 +37,7 @@
 | 
			
		||||
#include <boost/beast/websocket/stream_base.hpp>
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
@@ -91,7 +91,7 @@ TestWsServer::TestWsServer(asio::io_context& context, std::string const& host, i
 | 
			
		||||
    acceptor_.bind(endpoint);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
util::Expected<TestWsConnection, util::requests::RequestError>
 | 
			
		||||
std::expected<TestWsConnection, util::requests::RequestError>
 | 
			
		||||
TestWsServer::acceptConnection(asio::yield_context yield)
 | 
			
		||||
{
 | 
			
		||||
    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());
 | 
			
		||||
    acceptor_.async_accept(socket, yield[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));
 | 
			
		||||
    ws.set_option(websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
 | 
			
		||||
    ws.async_accept(yield[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));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
 | 
			
		||||
#include <boost/asio/io_context.hpp>
 | 
			
		||||
@@ -28,6 +27,7 @@
 | 
			
		||||
#include <boost/beast/core/tcp_stream.hpp>
 | 
			
		||||
#include <boost/beast/websocket/stream.hpp>
 | 
			
		||||
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
@@ -59,7 +59,7 @@ class TestWsServer {
 | 
			
		||||
public:
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/MockOperation.hpp"
 | 
			
		||||
#include "util/async/AnyOperation.hpp"
 | 
			
		||||
#include "util/async/Error.hpp"
 | 
			
		||||
@@ -26,14 +25,15 @@
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <any>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
using namespace util::async;
 | 
			
		||||
using namespace ::testing;
 | 
			
		||||
 | 
			
		||||
struct AnyOperationTests : Test {
 | 
			
		||||
    using OperationType = MockOperation<util::Expected<impl::Any, ExecutionError>>;
 | 
			
		||||
    using ScheduledOperationType = MockScheduledOperation<util::Expected<impl::Any, ExecutionError>>;
 | 
			
		||||
    using OperationType = MockOperation<std::expected<impl::Any, ExecutionError>>;
 | 
			
		||||
    using ScheduledOperationType = MockScheduledOperation<std::expected<impl::Any, ExecutionError>>;
 | 
			
		||||
 | 
			
		||||
    NaggyMock<OperationType> mockOp;
 | 
			
		||||
    NaggyMock<ScheduledOperationType> mockScheduledOp;
 | 
			
		||||
@@ -46,7 +46,7 @@ using AnyOperationDeathTest = AnyOperationTests;
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
    auto res = voidOp.get();
 | 
			
		||||
    ASSERT_TRUE(res);
 | 
			
		||||
@@ -85,7 +85,7 @@ TEST_F(AnyOperationTests, RequestStopCallPropagated)
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
    ASSERT_FALSE(res);
 | 
			
		||||
    EXPECT_TRUE(res.error().message.ends_with("Not good"));
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/MockOperation.hpp"
 | 
			
		||||
#include "util/MockStrand.hpp"
 | 
			
		||||
#include "util/async/AnyOperation.hpp"
 | 
			
		||||
@@ -29,6 +28,7 @@
 | 
			
		||||
 | 
			
		||||
#include <any>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/Fixtures.hpp"
 | 
			
		||||
#include "util/TestHttpServer.hpp"
 | 
			
		||||
#include "util/requests/RequestBuilder.hpp"
 | 
			
		||||
@@ -32,6 +31,7 @@
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
@@ -111,14 +111,14 @@ TEST_P(RequestBuilderTest, SimpleRequest)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
                case http::verb::get:
 | 
			
		||||
                    return builder.getPlain(yield);
 | 
			
		||||
                case http::verb::post:
 | 
			
		||||
                    return builder.postPlain(yield);
 | 
			
		||||
                default:
 | 
			
		||||
                    return util::Unexpected{RequestError{"Invalid HTTP verb"}};
 | 
			
		||||
                    return std::unexpected{RequestError{"Invalid HTTP verb"}};
 | 
			
		||||
            }
 | 
			
		||||
        }();
 | 
			
		||||
        ASSERT_TRUE(response) << response.error().message();
 | 
			
		||||
@@ -243,14 +243,14 @@ TEST_P(RequestBuilderSslTest, TrySslUsePlain)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
                case http::verb::get:
 | 
			
		||||
                    return builder.get(yield);
 | 
			
		||||
                case http::verb::post:
 | 
			
		||||
                    return builder.post(yield);
 | 
			
		||||
                default:
 | 
			
		||||
                    return util::Unexpected{RequestError{"Invalid HTTP verb"}};
 | 
			
		||||
                    return std::unexpected{RequestError{"Invalid HTTP verb"}};
 | 
			
		||||
            }
 | 
			
		||||
        }();
 | 
			
		||||
        ASSERT_TRUE(response) << response.error().message();
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/Expected.hpp"
 | 
			
		||||
#include "util/Fixtures.hpp"
 | 
			
		||||
#include "util/TestWsServer.hpp"
 | 
			
		||||
#include "util/requests/Types.hpp"
 | 
			
		||||
@@ -29,6 +28,7 @@
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <expected>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
@@ -44,7 +44,7 @@ struct WsConnectionTestsBase : SyncAsioContextTest {
 | 
			
		||||
 | 
			
		||||
    template <typename T, typename E>
 | 
			
		||||
    T
 | 
			
		||||
    unwrap(util::Expected<T, E> expected)
 | 
			
		||||
    unwrap(std::expected<T, E> expected)
 | 
			
		||||
    {
 | 
			
		||||
        [&]() { ASSERT_TRUE(expected.has_value()) << expected.error().message(); }();
 | 
			
		||||
        return std::move(expected).value();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user