rpc: Add MaybeArg() and Arg() default helper

This commit is contained in:
MarcoFalke
2023-08-07 14:53:42 +02:00
parent cd5d2f5f09
commit c00000df16
5 changed files with 113 additions and 8 deletions

View File

@@ -609,7 +609,10 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
if (!arg_mismatch.empty()) {
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Wrong type passed:\n%s", arg_mismatch.write(4)));
}
CHECK_NONFATAL(m_req == nullptr);
m_req = &request;
UniValue ret = m_fun(*this, request);
m_req = nullptr;
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
UniValue mismatch{UniValue::VARR};
for (const auto& res : m_results.m_results) {
@@ -635,6 +638,49 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
return ret;
}
using CheckFn = void(const RPCArg&);
static const UniValue* DetailMaybeArg(CheckFn* check, const std::vector<RPCArg>& params, const JSONRPCRequest* req, size_t i)
{
CHECK_NONFATAL(i < params.size());
const UniValue& arg{CHECK_NONFATAL(req)->params[i]};
const RPCArg& param{params.at(i)};
if (check) check(param);
if (!arg.isNull()) return &arg;
if (!std::holds_alternative<RPCArg::Default>(param.m_fallback)) return nullptr;
return &std::get<RPCArg::Default>(param.m_fallback);
}
static void CheckRequiredOrDefault(const RPCArg& param)
{
// Must use `Arg<Type>(i)` to get the argument or its default value.
const bool required{
std::holds_alternative<RPCArg::Optional>(param.m_fallback) && RPCArg::Optional::NO == std::get<RPCArg::Optional>(param.m_fallback),
};
CHECK_NONFATAL(required || std::holds_alternative<RPCArg::Default>(param.m_fallback));
}
#define TMPL_INST(check_param, ret_type, return_code) \
template <> \
ret_type RPCHelpMan::ArgValue<ret_type>(size_t i) const \
{ \
const UniValue* maybe_arg{ \
DetailMaybeArg(check_param, m_args, m_req, i), \
}; \
return return_code \
} \
void force_semicolon(ret_type)
// Optional arg (without default). Can also be called on required args, if needed.
TMPL_INST(nullptr, std::optional<double>, maybe_arg ? std::optional{maybe_arg->get_real()} : std::nullopt;);
TMPL_INST(nullptr, std::optional<bool>, maybe_arg ? std::optional{maybe_arg->get_bool()} : std::nullopt;);
TMPL_INST(nullptr, const std::string*, maybe_arg ? &maybe_arg->get_str() : nullptr;);
// Required arg or optional arg with default value.
TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>(););
TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>(););
TMPL_INST(CheckRequiredOrDefault, const std::string&, CHECK_NONFATAL(maybe_arg)->get_str(););
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
{
size_t num_required_args = 0;