mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
rpc: add named arg helper
Overload the Arg and MaybeArg helpers to allow accessing arguments by name as well. Also update the docs to document Arg and MaybeArg separately
This commit is contained in:
parent
13525e0c24
commit
bbb31269bf
3 changed files with 78 additions and 10 deletions
|
@ -24,6 +24,8 @@
|
|||
#include <util/string.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
|
@ -728,6 +730,16 @@ std::vector<std::pair<std::string, bool>> RPCHelpMan::GetArgNames() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t RPCHelpMan::GetParamIndex(std::string_view key) const
|
||||
{
|
||||
auto it{std::find_if(
|
||||
m_args.begin(), m_args.end(), [&key](const auto& arg) { return arg.GetName() == key;}
|
||||
)};
|
||||
|
||||
CHECK_NONFATAL(it != m_args.end()); // TODO: ideally this is checked at compile time
|
||||
return std::distance(m_args.begin(), it);
|
||||
}
|
||||
|
||||
std::string RPCHelpMan::ToString() const
|
||||
{
|
||||
std::string ret;
|
||||
|
|
|
@ -402,18 +402,25 @@ public:
|
|||
|
||||
UniValue HandleRequest(const JSONRPCRequest& request) const;
|
||||
/**
|
||||
* Helper to get a request argument.
|
||||
* This function only works during m_fun(), i.e. it should only be used in
|
||||
* RPC method implementations. The helper internally checks whether the
|
||||
* user-passed argument isNull() and parses (from JSON) and returns the
|
||||
* user-passed argument, or the default value derived from the RPCArg
|
||||
* documentation, or a falsy value if no default was given.
|
||||
* @brief Helper to get a required or default-valued request argument.
|
||||
*
|
||||
* Use Arg<Type>(i) to get the argument or its default value. Otherwise,
|
||||
* use MaybeArg<Type>(i) to get the optional argument or a falsy value.
|
||||
* Use this function when the argument is required or when it has a default value. If the
|
||||
* argument is optional and may not be provided, use MaybeArg instead.
|
||||
*
|
||||
* The Type passed to this helper must match the corresponding
|
||||
* RPCArg::Type.
|
||||
* This function only works during m_fun(), i.e., it should only be used in
|
||||
* RPC method implementations. It internally checks whether the user-passed
|
||||
* argument isNull() and parses (from JSON) and returns the user-passed argument,
|
||||
* or the default value derived from the RPCArg documentation.
|
||||
*
|
||||
* There are two overloads of this function:
|
||||
* - Use Arg<Type>(size_t i) to get the argument (or the default value) by index.
|
||||
* - Use Arg<Type>(const std::string& key) to get the argument (or the default value) by key.
|
||||
*
|
||||
* The Type passed to this helper must match the corresponding RPCArg::Type.
|
||||
*
|
||||
* @return The value of the RPC argument (or the default value) cast to type Type.
|
||||
*
|
||||
* @see MaybeArg for handling optional arguments without default values.
|
||||
*/
|
||||
template <typename R>
|
||||
auto Arg(size_t i) const
|
||||
|
@ -427,6 +434,34 @@ public:
|
|||
return ArgValue<const R&>(i);
|
||||
}
|
||||
}
|
||||
template<typename R>
|
||||
auto Arg(std::string_view key) const
|
||||
{
|
||||
return Arg<R>(GetParamIndex(key));
|
||||
}
|
||||
/**
|
||||
* @brief Helper to get an optional request argument.
|
||||
*
|
||||
* Use this function when the argument is optional and does not have a default value. If the
|
||||
* argument is required or has a default value, use Arg instead.
|
||||
*
|
||||
* This function only works during m_fun(), i.e., it should only be used in
|
||||
* RPC method implementations. It internally checks whether the user-passed
|
||||
* argument isNull() and parses (from JSON) and returns the user-passed argument,
|
||||
* or a falsy value if no argument was passed.
|
||||
*
|
||||
* There are two overloads of this function:
|
||||
* - Use MaybeArg<Type>(size_t i) to get the optional argument by index.
|
||||
* - Use MaybeArg<Type>(const std::string& key) to get the optional argument by key.
|
||||
*
|
||||
* The Type passed to this helper must match the corresponding RPCArg::Type.
|
||||
*
|
||||
* @return For integral and floating-point types, a std::optional<Type> is returned.
|
||||
* For other types, a Type* pointer to the argument is returned. If the
|
||||
* argument is not provided, std::nullopt or a null pointer is returned.
|
||||
*
|
||||
* @see Arg for handling arguments that are required or have a default value.
|
||||
*/
|
||||
template <typename R>
|
||||
auto MaybeArg(size_t i) const
|
||||
{
|
||||
|
@ -439,6 +474,11 @@ public:
|
|||
return ArgValue<const R*>(i);
|
||||
}
|
||||
}
|
||||
template<typename R>
|
||||
auto MaybeArg(std::string_view key) const
|
||||
{
|
||||
return MaybeArg<R>(GetParamIndex(key));
|
||||
}
|
||||
std::string ToString() const;
|
||||
/** Return the named args that need to be converted from string to another JSON type */
|
||||
UniValue GetArgMap() const;
|
||||
|
@ -458,6 +498,8 @@ private:
|
|||
mutable const JSONRPCRequest* m_req{nullptr}; // A pointer to the request for the duration of m_fun()
|
||||
template <typename R>
|
||||
R ArgValue(size_t i) const;
|
||||
//! Return positional index of a parameter using its name as key.
|
||||
size_t GetParamIndex(std::string_view key) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -633,6 +633,20 @@ BOOST_AUTO_TEST_CASE(rpc_arg_helper)
|
|||
};
|
||||
CheckRpc(params, UniValue{JSON(R"([5, "hello", null, null, null, null, null])")}, check_positional);
|
||||
CheckRpc(params, UniValue{JSON(R"([5, "hello", 4, "test", true, 1.23, "world"])")}, check_positional);
|
||||
|
||||
//! Check that `self.Arg` returns the same value when using index and key
|
||||
RPCHelpMan::RPCMethodImpl check_named = [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
|
||||
BOOST_CHECK_EQUAL(self.Arg<int>(0), self.Arg<int>("req_int"));
|
||||
BOOST_CHECK_EQUAL(self.Arg<std::string>(1), self.Arg<std::string>("req_str"));
|
||||
BOOST_CHECK_EQUAL(self.Arg<uint64_t>(2), self.Arg<uint64_t>("def_uint64_t"));
|
||||
BOOST_CHECK_EQUAL(self.Arg<std::string>(3), self.Arg<std::string>("def_string"));
|
||||
BOOST_CHECK_EQUAL(self.Arg<bool>(4), self.Arg<bool>("def_bool"));
|
||||
BOOST_CHECK(self.MaybeArg<double>(5) == self.MaybeArg<double>("opt_double"));
|
||||
BOOST_CHECK(self.MaybeArg<std::string>(6) == self.MaybeArg<std::string>("opt_string"));
|
||||
return UniValue{};
|
||||
};
|
||||
CheckRpc(params, UniValue{JSON(R"([5, "hello", null, null, null, null, null])")}, check_named);
|
||||
CheckRpc(params, UniValue{JSON(R"([5, "hello", 4, "test", true, 1.23, "world"])")}, check_named);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Add table
Reference in a new issue