rpc: Auto-format RPCResult

This commit is contained in:
MarcoFalke
2020-01-10 00:00:57 +07:00
parent fa7d0503d3
commit fa6b061fc1
11 changed files with 1475 additions and 1207 deletions

View File

@@ -433,7 +433,9 @@ std::string RPCResults::ToDescriptionString() const
} else {
result += "\nResult (" + r.m_cond + "):\n";
}
result += r.m_result;
Sections sections;
r.ToSections(sections);
result += sections.ToString();
}
return result;
}
@@ -580,6 +582,93 @@ std::string RPCArg::ToDescriptionString() const
return ret;
}
void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const int current_indent) const
{
// Indentation
const std::string indent(current_indent, ' ');
const std::string indent_next(current_indent + 2, ' ');
// Elements in a JSON structure (dictionary or array) are separated by a comma
const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""};
// The key name if recursed into an dictionary
const std::string maybe_key{
outer_type == OuterType::OBJ ?
"\"" + this->m_key_name + "\" : " :
""};
// Format description with type
const auto Description = [&](const std::string& type) {
return "(" + type + (this->m_optional ? ", optional" : "") + ")" +
(this->m_description.empty() ? "" : " " + this->m_description);
};
switch (m_type) {
case Type::ELISION: {
// If the inner result is empty, use three dots for elision
sections.PushSection({indent_next + "...", m_description});
return;
}
case Type::NONE: {
sections.PushSection({indent + "None", Description("json null")});
return;
}
case Type::STR: {
sections.PushSection({indent + maybe_key + "\"str\"" + maybe_separator, Description("string")});
return;
}
case Type::STR_AMOUNT: {
sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
return;
}
case Type::STR_HEX: {
sections.PushSection({indent + maybe_key + "\"hex\"" + maybe_separator, Description("string")});
return;
}
case Type::NUM: {
sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
return;
}
case Type::NUM_TIME: {
sections.PushSection({indent + maybe_key + "xxx" + maybe_separator, Description("numeric")});
return;
}
case Type::BOOL: {
sections.PushSection({indent + maybe_key + "true|false" + maybe_separator, Description("boolean")});
return;
}
case Type::ARR_FIXED:
case Type::ARR: {
sections.PushSection({indent + maybe_key + "[", Description("json array")});
for (const auto& i : m_inner) {
i.ToSections(sections, OuterType::ARR, current_indent + 2);
}
if (m_type == Type::ARR) {
sections.PushSection({indent_next + "...", ""});
}
sections.PushSection({indent + "]" + maybe_separator, ""});
return;
}
case Type::OBJ_DYN:
case Type::OBJ: {
sections.PushSection({indent + maybe_key + "{", Description("json object")});
for (const auto& i : m_inner) {
i.ToSections(sections, OuterType::OBJ, current_indent + 2);
}
if (m_type == Type::OBJ_DYN) {
// If the dictionary keys are dynamic, use three dots for continuation
sections.PushSection({indent_next + "...", ""});
}
sections.PushSection({indent + "}" + maybe_separator, ""});
return;
}
// no default case, so the compiler can warn about missing cases
}
CHECK_NONFATAL(false);
}
std::string RPCArg::ToStringObj(const bool oneline) const
{
std::string res;