Size: 3806 bytes.


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// cs/parsers/arg_parser.gpt.hh
#ifndef CS_PARSERS_ARG_PARSER_GPT_HH
#define CS_PARSERS_ARG_PARSER_GPT_HH

#include <sstream>
#include <string>
#include <vector>

#include "cs/net/json/object.hh"
#include "cs/net/json/serialize.hh"
#include "cs/net/proto/proto.hh"
#include "cs/net/proto/protos/meta.proto.hh"
#include "cs/parsers/parsers.hh"
#include "cs/result.hh"

namespace cs::parsers {

// Parses command-line arguments and constructs a proto
// instance. Arguments should be in the format
// --field=value. Boolean flags must be explicitly set:
// --flag=true or --flag=false. Fields not specified will
// use their default values.
template <typename T>
cs::ResultOr<T> ParseArgs(std::vector<std::string> argv) {
  // Skip argv[0] (program name).
  if (argv.empty()) {
    return cs::InvalidArgument("argv cannot be empty");
  }

  // Get metadata about the proto fields.
  T instance{};
  auto meta = instance.Meta();

  // Build a map of field names to values from argv.
  cs::net::json::Object::KVMap kv_map;

  for (size_t i = 1; i < argv.size(); ++i) {
    const std::string& arg = argv[i];

    // Must start with --.
    if (arg.size() < 3 || arg[0] != '-' || arg[1] != '-') {
      return cs::InvalidArgument(
          "Argument must start with --: " + arg);
    }

    // Find the = separator.
    size_t eq_pos = arg.find('=');
    if (eq_pos == std::string::npos) {
      return cs::InvalidArgument(
          "Argument must be in format --field=value: " +
          arg);
    }

    std::string field_name = arg.substr(2, eq_pos - 2);
    std::string field_value = arg.substr(eq_pos + 1);

    // Find the field in metadata.
    bool found = false;
    for (const auto& field_meta : meta.fields) {
      if (field_meta.name == field_name) {
        found = true;

        // Parse the value based on the field type.
        std::string type_str = field_meta.type;
        cs::net::json::Object value_obj;

        if (type_str == "bool") {
          if (field_value == "true") {
            value_obj =
                cs::net::json::Object::NewBool(true);
          } else if (field_value == "false") {
            value_obj =
                cs::net::json::Object::NewBool(false);
          } else {
            return cs::InvalidArgument(
                "Boolean field must be 'true' or 'false': "
                "--" +
                field_name + "=" + field_value);
          }
        } else if (type_str == "std::string") {
          value_obj =
              cs::net::json::Object::NewString(field_value);
        } else if (type_str == "int") {
          SET_OR_RET(int int_value,
                     cs::parsers::ParseInt(field_value));
          value_obj =
              cs::net::json::Object::NewInt(int_value);
        } else if (type_str == "float") {
          SET_OR_RET(float float_value,
                     cs::parsers::ParseFloat(field_value));
          value_obj =
              cs::net::json::Object::NewFloat(float_value);
        } else {
          // For other types (vectors, maps, nested protos),
          // treat as string and let the proto parser handle
          // it.
          value_obj =
              cs::net::json::Object::NewString(field_value);
        }

        kv_map[field_name] = value_obj;
        break;
      }
    }

    if (!found) {
      return cs::InvalidArgument(
          "Unknown field: --" + field_name +
          " (not found in proto metadata)");
    }
  }

  // Convert the map to a JSON string.
  cs::net::json::Object json_obj(kv_map);
  std::ostringstream oss;
  cs::net::json::SerializeObject(oss, json_obj);
  std::string json_str = oss.str();

  // Parse the JSON string to construct the proto instance.
  return instance.Parse(json_str);
}

}  // namespace cs::parsers

#endif  // CS_PARSERS_ARG_PARSER_GPT_HH
v0 (commit) © 2025 @p13i.io | Load balancer proxied to: cs-code-viewer-1:8080 in 4ms.