Repository: firecracker-microvm/firecracker
File: src/utils/src/arg_parser.rs (Rust)

Code before:
    fn split_args(args: &[String]) -> (&[String], &[String]) {
        if let Some(index) = args.iter().position(|arg| arg == ARG_SEPARATOR) {
            return (&args[..index], &args[index + 1..]);
        }

        (args, &[])
    }

    /// Collect the command line arguments and the values provided for them.
    pub fn parse_from_cmdline(&mut self) -> Result<()> {
        let args: Vec<String> = env::args().collect();

        self.parse(&args)
    }

    /// Clear split between the actual arguments of the process, the extra arguments if any
    /// and the `--help` and `--version` arguments if present.
    pub fn parse(&mut self, args: &[String]) -> Result<()> {
        // Skipping the first element of `args` as it is the name of the binary.
        let (args, extra_args) = Arguments::split_args(&args[1..]);
        self.extra_args = extra_args.to_vec();

        // If `--help` or `-h`is provided as a parameter, we artificially skip the parsing of other
        // command line arguments by adding just the help argument to the parsed list and
        // returning.
        if args.contains(&HELP_ARG.to_string() || &SHORT_HELP_ARG.to_string()) {
            let mut help_arg = Argument::new("help").help("Show the help message.");
            help_arg.user_value = Some(Value::Flag);
            self.insert_arg(help_arg);
            return Ok(());
        }

        // If `--version` is provided as a parameter, we artificially skip the parsing of other
        // command line arguments by adding just the version argument to the parsed list and
        // returning.
        if args.contains(&VERSION_ARG.to_string()) {
            let mut version_arg = Argument::new("version");
            version_arg.user_value = Some(Value::Flag);
            self.insert_arg(version_arg);
            return Ok(());
        }

        // Otherwise, we continue the parsing of the other arguments.
        self.populate_args(args)
    }

    // Check if `required`, `requires` and `forbids` field rules are indeed followed by every
    // argument.
    fn validate_requirements(&self, args: &[String]) -> Result<()> {
        for argument in self.args.values() {
            // The arguments that are marked `required` must be provided by user.

Review comment (suggestion):
I think what you want to express here is

```suggestion
        if args.contains(&HELP_ARG.to_string()) || args.contains(&SHORT_HELP_ARG.to_string()) {
```

but that wouldn't really work because then even something like `./jailer --hello` would end up printing the help text :/

Code after:
    fn split_args(args: &[String]) -> (&[String], &[String]) {
        if let Some(index) = args.iter().position(|arg| arg == ARG_SEPARATOR) {
            return (&args[..index], &args[index + 1..]);
        }

        (args, &[])
    }

    /// Collect the command line arguments and the values provided for them.
    pub fn parse_from_cmdline(&mut self) -> Result<()> {
        let args: Vec<String> = env::args().collect();

        self.parse(&args)
    }

    /// Clear split between the actual arguments of the process, the extra arguments if any
    /// and the `--help` and `--version` arguments if present.
    pub fn parse(&mut self, args: &[String]) -> Result<()> {
        // Skipping the first element of `args` as it is the name of the binary.
        let (args, extra_args) = Arguments::split_args(&args[1..]);
        self.extra_args = extra_args.to_vec();

        // If `--help` or `-h`is provided as a parameter, we artificially skip the parsing of other
        // command line arguments by adding just the help argument to the parsed list and
        // returning.
        if args.contains(&HELP_ARG.to_string()) || args.contains(&SHORT_HELP_ARG.to_string()) {
            let mut help_arg = Argument::new("help").help("Show the help message.");
            help_arg.user_value = Some(Value::Flag);
            self.insert_arg(help_arg);
            return Ok(());
        }

        // If `--version` is provided as a parameter, we artificially skip the parsing of other
        // command line arguments by adding just the version argument to the parsed list and
        // returning.
        if args.contains(&VERSION_ARG.to_string()) {
            let mut version_arg = Argument::new("version");
            version_arg.user_value = Some(Value::Flag);
            self.insert_arg(version_arg);
            return Ok(());
        }

        // Otherwise, we continue the parsing of the other arguments.
        self.populate_args(args)
    }

    // Check if `required`, `requires` and `forbids` field rules are indeed followed by every
    // argument.
    fn validate_requirements(&self, args: &[String]) -> Result<()> {
        for argument in self.args.values() {
            // The arguments that are marked `required` must be provided by user.