* Recursive helper to translate an RPCArg into sections */ NOLINTNEXTLINE(misc-no-recursion)
| 444 | */ |
| 445 | // NOLINTNEXTLINE(misc-no-recursion) |
| 446 | void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NONE) |
| 447 | { |
| 448 | const auto indent = std::string(current_indent, ' '); |
| 449 | const auto indent_next = std::string(current_indent + 2, ' '); |
| 450 | const bool push_name{outer_type == OuterType::OBJ}; // Dictionary keys must have a name |
| 451 | const bool is_top_level_arg{outer_type == OuterType::NONE}; // True on the first recursion |
| 452 | |
| 453 | switch (arg.m_type) { |
| 454 | case RPCArg::Type::STR_HEX: |
| 455 | case RPCArg::Type::STR: |
| 456 | case RPCArg::Type::NUM: |
| 457 | case RPCArg::Type::AMOUNT: |
| 458 | case RPCArg::Type::RANGE: |
| 459 | case RPCArg::Type::BOOL: |
| 460 | case RPCArg::Type::OBJ_NAMED_PARAMS: { |
| 461 | if (is_top_level_arg) return; // Nothing more to do for non-recursive types on first recursion |
| 462 | auto left = indent; |
| 463 | if (arg.m_opts.type_str.size() != 0 && push_name) { |
| 464 | left += "\"" + arg.GetName() + "\": " + arg.m_opts.type_str.at(0); |
| 465 | } else { |
| 466 | left += push_name ? arg.ToStringObj(/*oneline=*/false) : arg.ToString(/*oneline=*/false); |
| 467 | } |
| 468 | left += ","; |
| 469 | PushSection({left, arg.ToDescriptionString(/*is_named_arg=*/push_name)}); |
| 470 | break; |
| 471 | } |
| 472 | case RPCArg::Type::OBJ: |
| 473 | case RPCArg::Type::OBJ_USER_KEYS: { |
| 474 | const auto right = is_top_level_arg ? "" : arg.ToDescriptionString(/*is_named_arg=*/push_name); |
| 475 | PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right}); |
| 476 | for (const auto& arg_inner : arg.m_inner) { |
| 477 | Push(arg_inner, current_indent + 2, OuterType::OBJ); |
| 478 | } |
| 479 | if (arg.m_type != RPCArg::Type::OBJ) { |
| 480 | PushSection({indent_next + "...", ""}); |
| 481 | } |
| 482 | PushSection({indent + "}" + (is_top_level_arg ? "" : ","), ""}); |
| 483 | break; |
| 484 | } |
| 485 | case RPCArg::Type::ARR: { |
| 486 | auto left = indent; |
| 487 | left += push_name ? "\"" + arg.GetName() + "\": " : ""; |
| 488 | left += "["; |
| 489 | const auto right = is_top_level_arg ? "" : arg.ToDescriptionString(/*is_named_arg=*/push_name); |
| 490 | PushSection({left, right}); |
| 491 | for (const auto& arg_inner : arg.m_inner) { |
| 492 | Push(arg_inner, current_indent + 2, OuterType::ARR); |
| 493 | } |
| 494 | PushSection({indent_next + "...", ""}); |
| 495 | PushSection({indent + "]" + (is_top_level_arg ? "" : ","), ""}); |
| 496 | break; |
| 497 | } |
| 498 | } // no default case, so the compiler can warn about missing cases |
| 499 | } |
| 500 | |
| 501 | /** |
| 502 | * Concatenate all sections with proper padding |