From 8a91ba85c4a1b98901b9f405ee2f3b303de0117c Mon Sep 17 00:00:00 2001 From: Alex Kremer Date: Wed, 26 Aug 2026 14:07:58 +0100 Subject: [PATCH 1/2] refactor: Separate handler registry (#3169) --- src/rpc/CMakeLists.txt | 1 + src/rpc/common/impl/HandlerProvider.cpp | 113 ++------ src/rpc/common/impl/HandlerRegistry.cpp | 328 ++++++++++++++++++++++++ src/rpc/common/impl/HandlerRegistry.hpp | 79 ++++++ 4 files changed, 431 insertions(+), 90 deletions(-) create mode 100644 src/rpc/common/impl/HandlerRegistry.cpp create mode 100644 src/rpc/common/impl/HandlerRegistry.hpp diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 544d40494..ba402697b 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -21,6 +21,7 @@ target_sources( common/MetaProcessors.cpp common/impl/APIVersionParser.cpp common/impl/HandlerProvider.cpp + common/impl/HandlerRegistry.cpp filters/impl/DelegateTransactionsFilter.cpp handlers/AccountChannels.cpp handlers/AccountCurrencies.cpp diff --git a/src/rpc/common/impl/HandlerProvider.cpp b/src/rpc/common/impl/HandlerProvider.cpp index c199753c8..3e42c5db9 100644 --- a/src/rpc/common/impl/HandlerProvider.cpp +++ b/src/rpc/common/impl/HandlerProvider.cpp @@ -5,47 +5,8 @@ #include "etl/ETLServiceInterface.hpp" #include "etl/LoadBalancerInterface.hpp" #include "feed/SubscriptionManagerInterface.hpp" -#include "rpc/Counters.hpp" #include "rpc/common/AnyHandler.hpp" -#include "rpc/handlers/AMMInfo.hpp" -#include "rpc/handlers/AccountChannels.hpp" -#include "rpc/handlers/AccountCurrencies.hpp" -#include "rpc/handlers/AccountInfo.hpp" -#include "rpc/handlers/AccountLines.hpp" -#include "rpc/handlers/AccountMPTokenIssuances.hpp" -#include "rpc/handlers/AccountMPTokens.hpp" -#include "rpc/handlers/AccountNFTs.hpp" -#include "rpc/handlers/AccountObjects.hpp" -#include "rpc/handlers/AccountOffers.hpp" -#include "rpc/handlers/AccountTx.hpp" -#include "rpc/handlers/BookChanges.hpp" -#include "rpc/handlers/BookOffers.hpp" -#include "rpc/handlers/DepositAuthorized.hpp" -#include "rpc/handlers/Feature.hpp" -#include "rpc/handlers/GatewayBalances.hpp" -#include "rpc/handlers/GetAggregatePrice.hpp" -#include "rpc/handlers/Ledger.hpp" -#include "rpc/handlers/LedgerData.hpp" -#include "rpc/handlers/LedgerEntry.hpp" -#include "rpc/handlers/LedgerIndex.hpp" -#include "rpc/handlers/LedgerRange.hpp" -#include "rpc/handlers/MPTHolders.hpp" -#include "rpc/handlers/MPTokenIssuanceHistory.hpp" -#include "rpc/handlers/NFTBuyOffers.hpp" -#include "rpc/handlers/NFTHistory.hpp" -#include "rpc/handlers/NFTInfo.hpp" -#include "rpc/handlers/NFTSellOffers.hpp" -#include "rpc/handlers/NFTsByIssuer.hpp" -#include "rpc/handlers/NoRippleCheck.hpp" -#include "rpc/handlers/Ping.hpp" -#include "rpc/handlers/Random.hpp" -#include "rpc/handlers/ServerInfo.hpp" -#include "rpc/handlers/Subscribe.hpp" -#include "rpc/handlers/TransactionEntry.hpp" -#include "rpc/handlers/Tx.hpp" -#include "rpc/handlers/Unsubscribe.hpp" -#include "rpc/handlers/VaultInfo.hpp" -#include "rpc/handlers/VersionHandler.hpp" +#include "rpc/common/impl/HandlerRegistry.hpp" #include "util/config/ConfigDefinition.hpp" #include @@ -64,57 +25,29 @@ ProductionHandlerProvider::ProductionHandlerProvider( std::shared_ptr const& amendmentCenter, Counters const& counters ) - : handlerMap_{ - {"account_channels", {.handler = AccountChannelsHandler{backend}}}, - {"account_currencies", {.handler = AccountCurrenciesHandler{backend}}}, - {"account_info", {.handler = AccountInfoHandler{backend, amendmentCenter}}}, - {"account_lines", {.handler = AccountLinesHandler{backend}}}, - {"account_mptoken_issuances", - {.handler = AccountMPTokenIssuancesHandler{backend}, .isClioOnly = true}}, // clio only - {"account_mptokens", - {.handler = AccountMPTokensHandler{backend}, .isClioOnly = true}}, // clio only - {"account_nfts", {.handler = AccountNFTsHandler{backend}}}, - {"account_objects", {.handler = AccountObjectsHandler{backend}}}, - {"account_offers", {.handler = AccountOffersHandler{backend}}}, - {"account_tx", {.handler = AccountTxHandler{backend, etl}}}, - {"amm_info", {.handler = AMMInfoHandler{backend, amendmentCenter}}}, - {"book_changes", {.handler = BookChangesHandler{backend}}}, - {"book_offers", {.handler = BookOffersHandler{backend, amendmentCenter}}}, - {"deposit_authorized", {.handler = DepositAuthorizedHandler{backend}}}, - {"feature", {.handler = FeatureHandler{backend, amendmentCenter}}}, - {"gateway_balances", {.handler = GatewayBalancesHandler{backend}}}, - {"get_aggregate_price", {.handler = GetAggregatePriceHandler{backend}}}, - {"ledger", {.handler = LedgerHandler{backend, amendmentCenter}}}, - {"ledger_data", {.handler = LedgerDataHandler{backend}}}, - {"ledger_entry", {.handler = LedgerEntryHandler{backend}}}, - {"ledger_index", - {.handler = LedgerIndexHandler{backend}, .isClioOnly = true}}, // clio only - {"ledger_range", {.handler = LedgerRangeHandler{backend}}}, - {"mpt_holders", - {.handler = MPTHoldersHandler{backend}, .isClioOnly = true}}, // clio only - {"mptoken_issuance_history", - {.handler = MPTokenIssuanceHistoryHandler{backend}, .isClioOnly = true}}, // clio only - {"nfts_by_issuer", - {.handler = NFTsByIssuerHandler{backend}, .isClioOnly = true}}, // clio only - {"nft_history", - {.handler = NFTHistoryHandler{backend}, .isClioOnly = true}}, // clio only - {"nft_buy_offers", {.handler = NFTBuyOffersHandler{backend}}}, - {"nft_info", {.handler = NFTInfoHandler{backend}, .isClioOnly = true}}, // clio only - {"nft_sell_offers", {.handler = NFTSellOffersHandler{backend}}}, - {"noripple_check", {.handler = NoRippleCheckHandler{backend}}}, - {"ping", {.handler = PingHandler{}}}, - {"random", {.handler = RandomHandler{}}}, - {"server_info", - {.handler = ServerInfoHandler{backend, subscriptionManager, balancer, etl, counters}}}, - {"transaction_entry", {.handler = TransactionEntryHandler{backend}}}, - {"tx", {.handler = TxHandler{backend, etl}}}, - {"subscribe", - {.handler = SubscribeHandler{backend, amendmentCenter, subscriptionManager}}}, - {"unsubscribe", {.handler = UnsubscribeHandler{subscriptionManager}}}, - {"vault_info", {.handler = VaultInfoHandler{backend}}}, - {"version", {.handler = VersionHandler{config}}}, - } { + HandlerDeps const deps{ + .config = config, + .backend = backend, + .subscriptionManager = subscriptionManager, + .balancer = balancer, + .etl = etl, + .amendmentCenter = amendmentCenter, + .counters = counters + }; + + auto const registry = handlerRegistry(); + handlerMap_.reserve(registry.size()); + + for (auto const& entry : registry) { + handlerMap_.emplace( + entry.name, + Handler{ + .handler = entry.factory(deps), + .isClioOnly = entry.isClioOnly, + } + ); + } } bool diff --git a/src/rpc/common/impl/HandlerRegistry.cpp b/src/rpc/common/impl/HandlerRegistry.cpp new file mode 100644 index 000000000..755e0d0c5 --- /dev/null +++ b/src/rpc/common/impl/HandlerRegistry.cpp @@ -0,0 +1,328 @@ +#include "rpc/common/impl/HandlerRegistry.hpp" + +#include "rpc/Counters.hpp" // IWYU pragma: keep +#include "rpc/common/AnyHandler.hpp" +#include "rpc/handlers/AMMInfo.hpp" +#include "rpc/handlers/AccountChannels.hpp" +#include "rpc/handlers/AccountCurrencies.hpp" +#include "rpc/handlers/AccountInfo.hpp" +#include "rpc/handlers/AccountLines.hpp" +#include "rpc/handlers/AccountMPTokenIssuances.hpp" +#include "rpc/handlers/AccountMPTokens.hpp" +#include "rpc/handlers/AccountNFTs.hpp" +#include "rpc/handlers/AccountObjects.hpp" +#include "rpc/handlers/AccountOffers.hpp" +#include "rpc/handlers/AccountTx.hpp" +#include "rpc/handlers/BookChanges.hpp" +#include "rpc/handlers/BookOffers.hpp" +#include "rpc/handlers/DepositAuthorized.hpp" +#include "rpc/handlers/Feature.hpp" +#include "rpc/handlers/GatewayBalances.hpp" +#include "rpc/handlers/GetAggregatePrice.hpp" +#include "rpc/handlers/Ledger.hpp" +#include "rpc/handlers/LedgerData.hpp" +#include "rpc/handlers/LedgerEntry.hpp" +#include "rpc/handlers/LedgerIndex.hpp" +#include "rpc/handlers/LedgerRange.hpp" +#include "rpc/handlers/MPTHolders.hpp" +#include "rpc/handlers/MPTokenIssuanceHistory.hpp" +#include "rpc/handlers/NFTBuyOffers.hpp" +#include "rpc/handlers/NFTHistory.hpp" +#include "rpc/handlers/NFTInfo.hpp" +#include "rpc/handlers/NFTSellOffers.hpp" +#include "rpc/handlers/NFTsByIssuer.hpp" +#include "rpc/handlers/NoRippleCheck.hpp" +#include "rpc/handlers/Ping.hpp" +#include "rpc/handlers/Random.hpp" +#include "rpc/handlers/ServerInfo.hpp" +#include "rpc/handlers/Subscribe.hpp" +#include "rpc/handlers/TransactionEntry.hpp" +#include "rpc/handlers/Tx.hpp" +#include "rpc/handlers/Unsubscribe.hpp" +#include "rpc/handlers/VaultInfo.hpp" +#include "rpc/handlers/VersionHandler.hpp" +#include "util/Concepts.hpp" + +#include +#include +#include + +namespace rpc::impl { + +namespace { + +constexpr auto kHandlers = std::to_array({ + { + .name = "account_channels", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountChannelsHandler{d.backend}; + }, + }, + + { + .name = "account_currencies", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountCurrenciesHandler{d.backend}; + }, + }, + + { + .name = "account_info", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountInfoHandler{d.backend, d.amendmentCenter}; + }, + }, + + { + .name = "account_lines", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountLinesHandler{d.backend}; + }, + }, + + { + .name = "account_mptoken_issuances", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountMPTokenIssuancesHandler{d.backend}; + }, + .isClioOnly = true, + }, + + { + .name = "account_mptokens", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountMPTokensHandler{d.backend}; + }, + .isClioOnly = true, + }, + + { + .name = "account_nfts", + .factory = [](HandlerDeps const& d) -> AnyHandler { return AccountNFTsHandler{d.backend}; }, + }, + + { + .name = "account_objects", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountObjectsHandler{d.backend}; + }, + }, + + { + .name = "account_offers", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountOffersHandler{d.backend}; + }, + }, + + { + .name = "account_tx", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AccountTxHandler{d.backend, d.etl}; + }, + }, + + { + .name = "amm_info", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return AMMInfoHandler{d.backend, d.amendmentCenter}; + }, + }, + + { + .name = "book_changes", + .factory = [](HandlerDeps const& d) -> AnyHandler { return BookChangesHandler{d.backend}; }, + }, + + { + .name = "book_offers", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return BookOffersHandler{d.backend, d.amendmentCenter}; + }, + }, + + { + .name = "deposit_authorized", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return DepositAuthorizedHandler{d.backend}; + }, + }, + + { + .name = "feature", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return FeatureHandler{d.backend, d.amendmentCenter}; + }, + }, + + { + .name = "gateway_balances", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return GatewayBalancesHandler{d.backend}; + }, + }, + + { + .name = "get_aggregate_price", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return GetAggregatePriceHandler{d.backend}; + }, + }, + + { + .name = "ledger", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return LedgerHandler{d.backend, d.amendmentCenter}; + }, + }, + + { + .name = "ledger_data", + .factory = [](HandlerDeps const& d) -> AnyHandler { return LedgerDataHandler{d.backend}; }, + }, + + { + .name = "ledger_entry", + .factory = [](HandlerDeps const& d) -> AnyHandler { return LedgerEntryHandler{d.backend}; }, + }, + + { + .name = "ledger_index", + .factory = [](HandlerDeps const& d) -> AnyHandler { return LedgerIndexHandler{d.backend}; }, + .isClioOnly = true, + }, + + { + .name = "ledger_range", + .factory = [](HandlerDeps const& d) -> AnyHandler { return LedgerRangeHandler{d.backend}; }, + }, + + { + .name = "mpt_holders", + .factory = [](HandlerDeps const& d) -> AnyHandler { return MPTHoldersHandler{d.backend}; }, + .isClioOnly = true, + }, + + { + .name = "mptoken_issuance_history", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return MPTokenIssuanceHistoryHandler{d.backend}; + }, + .isClioOnly = true, + }, + + { + .name = "nfts_by_issuer", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return NFTsByIssuerHandler{d.backend}; + }, + .isClioOnly = true, + }, + + { + .name = "nft_history", + .factory = [](HandlerDeps const& d) -> AnyHandler { return NFTHistoryHandler{d.backend}; }, + .isClioOnly = true, + }, + + { + .name = "nft_buy_offers", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return NFTBuyOffersHandler{d.backend}; + }, + }, + + { + .name = "nft_info", + .factory = [](HandlerDeps const& d) -> AnyHandler { return NFTInfoHandler{d.backend}; }, + .isClioOnly = true, + }, + + { + .name = "nft_sell_offers", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return NFTSellOffersHandler{d.backend}; + }, + }, + + { + .name = "noripple_check", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return NoRippleCheckHandler{d.backend}; + }, + }, + + { + .name = "ping", + .factory = [](HandlerDeps const&) -> AnyHandler { return PingHandler{}; }, + }, + + { + .name = "random", + .factory = [](HandlerDeps const&) -> AnyHandler { return RandomHandler{}; }, + }, + + { + .name = "server_info", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return ServerInfoHandler{ + d.backend, d.subscriptionManager, d.balancer, d.etl, d.counters + }; + }, + }, + + { + .name = "transaction_entry", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return TransactionEntryHandler{d.backend}; + }, + }, + + { + .name = "tx", + .factory = [](HandlerDeps const& d) -> AnyHandler { return TxHandler{d.backend, d.etl}; }, + }, + + { + .name = "subscribe", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return SubscribeHandler{d.backend, d.amendmentCenter, d.subscriptionManager}; + }, + }, + + { + .name = "unsubscribe", + .factory = [](HandlerDeps const& d) -> AnyHandler { + return UnsubscribeHandler{d.subscriptionManager}; + }, + }, + + { + .name = "vault_info", + .factory = [](HandlerDeps const& d) -> AnyHandler { return VaultInfoHandler{d.backend}; }, + }, + + { + .name = "version", + .factory = [](HandlerDeps const& d) -> AnyHandler { return VersionHandler{d.config}; }, + }, +}); + +// A duplicate name would silently shadow a handler so we check at compile time. +static_assert( + std::apply( + [](auto const&... entry) { return util::hasNoDuplicates(entry.name...); }, + kHandlers + ), + "RPC handler names must be unique" +); + +} // namespace + +std::span +handlerRegistry() noexcept +{ + return kHandlers; +} + +} // namespace rpc::impl diff --git a/src/rpc/common/impl/HandlerRegistry.hpp b/src/rpc/common/impl/HandlerRegistry.hpp new file mode 100644 index 000000000..0b08b3c30 --- /dev/null +++ b/src/rpc/common/impl/HandlerRegistry.hpp @@ -0,0 +1,79 @@ +/** @file */ +#pragma once + +#include "rpc/common/AnyHandler.hpp" + +#include +#include +#include + +namespace data { +class AmendmentCenterInterface; +class BackendInterface; +} // namespace data + +namespace etl { +struct ETLServiceInterface; +class LoadBalancerInterface; +} // namespace etl + +namespace feed { +class SubscriptionManagerInterface; +} // namespace feed + +namespace util::config { +class ClioConfigDefinition; +} // namespace util::config + +namespace rpc { +class Counters; +} // namespace rpc + +namespace rpc::impl { + +/** + * @brief The bundle of runtime dependencies a handler factory may consume. + * + * A short-lived view over the caller's objects: it holds references only, so it must + * not outlive the call it is passed to. + */ +struct HandlerDeps { + util::config::ClioConfigDefinition const& config; + std::shared_ptr const& backend; + std::shared_ptr const& subscriptionManager; + std::shared_ptr const& balancer; + std::shared_ptr const& etl; + std::shared_ptr const& amendmentCenter; + Counters const& counters; +}; + +/** + * @brief Constructs one type-erased handler from the available dependencies. + * + * A plain function pointer rather than @c std::function so that the registry stays a + * literal type and is constant-initialised. + */ +using HandlerFactory = AnyHandler (*)(HandlerDeps const&); + +/** + * @brief One row of the handler registry: the method name, how to construct the + * handler, and its static metadata. + */ +struct HandlerEntry { + std::string_view name; + HandlerFactory factory; + bool isClioOnly = false; +}; + +/** + * @brief The full set of registered RPC handlers. + * + * Static data: reading the registry constructs no handler and requires no runtime + * dependencies. + * + * @return A span over the registry, valid for the lifetime of the program + */ +[[nodiscard]] std::span +handlerRegistry() noexcept; + +} // namespace rpc::impl From 4afc3fdb76bd3dee597df29ad24cea583a7a94f3 Mon Sep 17 00:00:00 2001 From: Alex Kremer Date: Wed, 26 Aug 2026 16:20:30 +0100 Subject: [PATCH 2/2] chore: Introduce `xrpl-rpc-spec` 0.1.6 dependency (#3171) --- CMakeLists.txt | 9 ++++--- cmake/deps/rpcspec.cmake | 1 + conan.lock | 9 ++++--- conanfile.py | 2 ++ src/rpc/CMakeLists.txt | 2 +- src/rpc/common/JsonBool.hpp | 51 +++---------------------------------- 6 files changed, 17 insertions(+), 57 deletions(-) create mode 100644 cmake/deps/rpcspec.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b68eca363..7d117e81c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,14 +75,15 @@ include(Settings) include(PatchNixBinary) # Clio deps -include(deps/libxrpl) include(deps/Boost) -include(deps/OpenSSL) -include(deps/Threads) -include(deps/libfmt) include(deps/cassandra) include(deps/libbacktrace) +include(deps/libfmt) +include(deps/libxrpl) +include(deps/OpenSSL) +include(deps/rpcspec) include(deps/spdlog) +include(deps/Threads) add_subdirectory(src) add_subdirectory(tests) diff --git a/cmake/deps/rpcspec.cmake b/cmake/deps/rpcspec.cmake new file mode 100644 index 000000000..c3a53dbc7 --- /dev/null +++ b/cmake/deps/rpcspec.cmake @@ -0,0 +1 @@ +find_package(xrpl-rpc-spec REQUIRED CONFIG) diff --git a/conan.lock b/conan.lock index 75cc25874..c0a1fcd70 100644 --- a/conan.lock +++ b/conan.lock @@ -3,6 +3,7 @@ "requires": [ "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708", "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688", + "xrpl-rpc-spec/0.1.6#0147dce06088874791dca62dc8503b6c%1787751048.16847", "xrpl/3.3.0#5e356a24ae1f0d6da6bd617b926f92e6%1786467262.262007", "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447", "spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1782736610.443882", @@ -54,13 +55,13 @@ "zlib/[>=1.2.11 <2]": [ "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb" ], + "boost/1.91.0": [ + "boost/1.91.0" + ], "zlib/1.3.2": [ null, "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb" ], - "boost/1.91.0": [ - "boost/1.91.0#ea540ca2133d831b560036aa24dece3c" - ], "protobuf/[>=5.27.0 <7]": [ "protobuf/6.33.5" ], @@ -74,7 +75,7 @@ "sqlite3/3.53.0" ], "boost/1.83.0": [ - "boost/1.91.0" + "boost/1.91.0#ea540ca2133d831b560036aa24dece3c" ], "openssl/[>=3.5 <4]": [ "openssl/3.6.3#f806de8933e3bf6f01016c6a888cee2e" diff --git a/conanfile.py b/conanfile.py index d638113c9..3ef0797cf 100644 --- a/conanfile.py +++ b/conanfile.py @@ -17,6 +17,7 @@ class ClioConan(ConanFile): "fmt/12.1.0", "libbacktrace/cci.20210118", "spdlog/1.17.0", + "xrpl-rpc-spec/0.1.6", "xrpl/3.3.0", ] @@ -32,6 +33,7 @@ class ClioConan(ConanFile): "protobuf/*:shared": False, "protobuf/*:with_zlib": True, "snappy/*:shared": False, + "xrpl-rpc-spec/*:server": "clio", "xrpl/*:rocksdb": True, # TODO: revert to false when includes are fixed in libxrpl "xrpl/*:tests": False, } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index ba402697b..73dbcade0 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -61,4 +61,4 @@ target_sources( handlers/VaultInfo.cpp ) -target_link_libraries(clio_rpc PUBLIC clio_util clio_data) +target_link_libraries(clio_rpc PUBLIC clio_util clio_data rpcspec::rpcspec) diff --git a/src/rpc/common/JsonBool.hpp b/src/rpc/common/JsonBool.hpp index 2962abaa3..964238915 100644 --- a/src/rpc/common/JsonBool.hpp +++ b/src/rpc/common/JsonBool.hpp @@ -1,58 +1,13 @@ #pragma once -#include -#include -#include -#include - -#include +#include namespace rpc { /** - * @brief A wrapper around bool that allows to convert from any JSON value - */ -struct JsonBool { - bool value = false; - - /** @cond */ - operator bool() const - { - return value; - } - /** @endcond */ -}; - -/** - * @brief Convert a JSON value to a JsonBool + * @brief A wrapper around bool that allows conversion from any JSON value. * - * @param jsonValue The JSON value to convert - * @return The converted JsonBool */ -inline JsonBool -tag_invoke(boost::json::value_to_tag const&, boost::json::value const& jsonValue) -{ - switch (jsonValue.kind()) { - case boost::json::kind::null: - return JsonBool{false}; - case boost::json::kind::bool_: - return JsonBool{jsonValue.as_bool()}; - case boost::json::kind::uint64: - [[fallthrough]]; - case boost::json::kind::int64: - return JsonBool{jsonValue.as_int64() != 0}; - case boost::json::kind::double_: - return JsonBool{jsonValue.as_double() != 0.0}; - case boost::json::kind::string: - // Also should be `jsonValue.as_string() != "false"` but rippled doesn't do - // that. Anyway for v2 api we have bool validation - return JsonBool{!jsonValue.as_string().empty() && jsonValue.as_string()[0] != 0}; - case boost::json::kind::array: - return JsonBool{!jsonValue.as_array().empty()}; - case boost::json::kind::object: - return JsonBool{!jsonValue.as_object().empty()}; - } - throw std::runtime_error("Invalid json value"); -} +using JsonBool = spec::JsonBool; } // namespace rpc