* Recursive helper to translate an RPCArg into sections */
| 417 | * Recursive helper to translate an RPCArg into sections |
| 418 | */ |
| 419 | void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NONE) |
| 420 | { |
| 421 | const auto indent = std::string(current_indent, ' '); |
| 422 | const auto indent_next = std::string(current_indent + 2, ' '); |
| 423 | const bool push_name{outer_type == OuterType::OBJ}; // Dictionary keys must have a name |
| 424 | |
| 425 | switch (arg.m_type) { |
| 426 | case RPCArg::Type::STR_HEX: |
| 427 | case RPCArg::Type::STR: |
| 428 | case RPCArg::Type::NUM: |
| 429 | case RPCArg::Type::AMOUNT: |
| 430 | case RPCArg::Type::RANGE: |
| 431 | case RPCArg::Type::BOOL: { |
| 432 | if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion |
| 433 | auto left = indent; |
| 434 | if (arg.m_type_str.size() != 0 && push_name) { |
| 435 | left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0); |
| 436 | } else { |
| 437 | left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false); |
| 438 | } |
| 439 | left += ","; |
| 440 | PushSection({left, arg.ToDescriptionString()}); |
| 441 | break; |
| 442 | } |
| 443 | case RPCArg::Type::OBJ: |
| 444 | case RPCArg::Type::OBJ_USER_KEYS: { |
| 445 | const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); |
| 446 | PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right}); |
| 447 | for (const auto& arg_inner : arg.m_inner) { |
| 448 | Push(arg_inner, current_indent + 2, OuterType::OBJ); |
| 449 | } |
| 450 | if (arg.m_type != RPCArg::Type::OBJ) { |
| 451 | PushSection({indent_next + "...", ""}); |
| 452 | } |
| 453 | PushSection({indent + "}" + (outer_type != OuterType::NONE ? "," : ""), ""}); |
| 454 | break; |
| 455 | } |
| 456 | case RPCArg::Type::ARR: { |
| 457 | auto left = indent; |
| 458 | left += push_name ? "\"" + arg.GetName() + "\": " : ""; |
| 459 | left += "["; |
| 460 | const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); |
| 461 | PushSection({left, right}); |
| 462 | for (const auto& arg_inner : arg.m_inner) { |
| 463 | Push(arg_inner, current_indent + 2, OuterType::ARR); |
| 464 | } |
| 465 | PushSection({indent_next + "...", ""}); |
| 466 | PushSection({indent + "]" + (outer_type != OuterType::NONE ? "," : ""), ""}); |
| 467 | break; |
| 468 | } |
| 469 | } // no default case, so the compiler can warn about missing cases |
| 470 | } |
| 471 | |
| 472 | /** |
| 473 | * Concatenate all sections with proper padding |