Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/util.cpp
Show First 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | struct Sections { | ||||
size_t m_max_pad{0}; | size_t m_max_pad{0}; | ||||
void PushSection(const Section &s) { | void PushSection(const Section &s) { | ||||
m_max_pad = std::max(m_max_pad, s.m_left.size()); | m_max_pad = std::max(m_max_pad, s.m_left.size()); | ||||
m_sections.push_back(s); | m_sections.push_back(s); | ||||
} | } | ||||
/** | /** | ||||
* Serializing RPCArgs depends on the outer type. Only arrays and | |||||
* dictionaries can be nested in json. The top-level outer type is "named | |||||
* arguments", a mix between a dictionary and arrays. | |||||
*/ | |||||
enum class OuterType { | |||||
ARR, | |||||
OBJ, | |||||
// Only set on first recursion | |||||
NAMED_ARG, | |||||
}; | |||||
/** | |||||
* Recursive helper to translate an RPCArg into sections | * Recursive helper to translate an RPCArg into sections | ||||
*/ | */ | ||||
void Push(const RPCArg &arg, const size_t current_indent = 5, | void Push(const RPCArg &arg, const size_t current_indent = 5, | ||||
const OuterType outer_type = OuterType::NAMED_ARG) { | const OuterType outer_type = OuterType::NONE) { | ||||
const auto indent = std::string(current_indent, ' '); | const auto indent = std::string(current_indent, ' '); | ||||
const auto indent_next = std::string(current_indent + 2, ' '); | const auto indent_next = std::string(current_indent + 2, ' '); | ||||
// Dictionary keys must have a name | // Dictionary keys must have a name | ||||
const bool push_name{outer_type == OuterType::OBJ}; | const bool push_name{outer_type == OuterType::OBJ}; | ||||
switch (arg.m_type) { | switch (arg.m_type) { | ||||
case RPCArg::Type::STR_HEX: | case RPCArg::Type::STR_HEX: | ||||
case RPCArg::Type::STR: | case RPCArg::Type::STR: | ||||
case RPCArg::Type::NUM: | case RPCArg::Type::NUM: | ||||
case RPCArg::Type::AMOUNT: | case RPCArg::Type::AMOUNT: | ||||
case RPCArg::Type::RANGE: | case RPCArg::Type::RANGE: | ||||
case RPCArg::Type::BOOL: { | case RPCArg::Type::BOOL: { | ||||
// Nothing more to do for non-recursive types on first recursion | // Nothing more to do for non-recursive types on first recursion | ||||
if (outer_type == OuterType::NAMED_ARG) { | if (outer_type == OuterType::NONE) { | ||||
return; | return; | ||||
} | } | ||||
auto left = indent; | auto left = indent; | ||||
if (arg.m_type_str.size() != 0 && push_name) { | if (arg.m_type_str.size() != 0 && push_name) { | ||||
left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0); | left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0); | ||||
} else { | } else { | ||||
left += push_name ? arg.ToStringObj(/* oneline */ false) | left += push_name ? arg.ToStringObj(/* oneline */ false) | ||||
: arg.ToString(/* oneline */ false); | : arg.ToString(/* oneline */ false); | ||||
} | } | ||||
left += ","; | left += ","; | ||||
PushSection({left, arg.ToDescriptionString()}); | PushSection({left, arg.ToDescriptionString()}); | ||||
break; | break; | ||||
} | } | ||||
case RPCArg::Type::OBJ: | case RPCArg::Type::OBJ: | ||||
case RPCArg::Type::OBJ_USER_KEYS: { | case RPCArg::Type::OBJ_USER_KEYS: { | ||||
const auto right = outer_type == OuterType::NAMED_ARG | const auto right = outer_type == OuterType::NONE | ||||
? "" | ? "" | ||||
: arg.ToDescriptionString(); | : arg.ToDescriptionString(); | ||||
PushSection({indent + | PushSection({indent + | ||||
(push_name ? "\"" + arg.m_name + "\": " : "") + | (push_name ? "\"" + arg.m_name + "\": " : "") + | ||||
"{", | "{", | ||||
right}); | right}); | ||||
for (const auto &arg_inner : arg.m_inner) { | for (const auto &arg_inner : arg.m_inner) { | ||||
Push(arg_inner, current_indent + 2, OuterType::OBJ); | Push(arg_inner, current_indent + 2, OuterType::OBJ); | ||||
} | } | ||||
if (arg.m_type != RPCArg::Type::OBJ) { | if (arg.m_type != RPCArg::Type::OBJ) { | ||||
PushSection({indent_next + "...", ""}); | PushSection({indent_next + "...", ""}); | ||||
} | } | ||||
PushSection( | PushSection( | ||||
{indent + "}" + | {indent + "}" + (outer_type != OuterType::NONE ? "," : ""), | ||||
(outer_type != OuterType::NAMED_ARG ? "," : ""), | |||||
""}); | ""}); | ||||
break; | break; | ||||
} | } | ||||
case RPCArg::Type::ARR: { | case RPCArg::Type::ARR: { | ||||
auto left = indent; | auto left = indent; | ||||
left += push_name ? "\"" + arg.m_name + "\": " : ""; | left += push_name ? "\"" + arg.m_name + "\": " : ""; | ||||
left += "["; | left += "["; | ||||
const auto right = outer_type == OuterType::NAMED_ARG | const auto right = outer_type == OuterType::NONE | ||||
? "" | ? "" | ||||
: arg.ToDescriptionString(); | : arg.ToDescriptionString(); | ||||
PushSection({left, right}); | PushSection({left, right}); | ||||
for (const auto &arg_inner : arg.m_inner) { | for (const auto &arg_inner : arg.m_inner) { | ||||
Push(arg_inner, current_indent + 2, OuterType::ARR); | Push(arg_inner, current_indent + 2, OuterType::ARR); | ||||
} | } | ||||
PushSection({indent_next + "...", ""}); | PushSection({indent_next + "...", ""}); | ||||
PushSection( | PushSection( | ||||
{indent + "]" + | {indent + "]" + (outer_type != OuterType::NONE ? "," : ""), | ||||
(outer_type != OuterType::NAMED_ARG ? "," : ""), | |||||
""}); | ""}); | ||||
break; | break; | ||||
} | } | ||||
// no default case, so the compiler can warn about missing cases | // no default case, so the compiler can warn about missing cases | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 404 Lines • Show Last 20 Lines |