aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/util.cpp
diff options
context:
space:
mode:
authorMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2023-08-07 14:53:42 +0200
committerMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2023-08-24 10:44:45 +0200
commitc00000df1605788acadceb90c22ae9f00db8a9dc (patch)
tree547e525ac6821f751bcca2dd9534043aa75fc382 /src/rpc/util.cpp
parentcd5d2f5f0938ad4f8737caf4e7c501101818fd36 (diff)
rpc: Add MaybeArg() and Arg() default helper
Diffstat (limited to 'src/rpc/util.cpp')
-rw-r--r--src/rpc/util.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 08a778a60e..45b7d89a7b 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -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;