Find the non-UTF-8 token clap actually rejected. Some arguments intentionally accept raw platform strings (`PathBuf`, `OsString`), so choosing the first or last invalid token can report the wrong bytes. Probe each candidate while replacing only later invalid tokens; the first candidate that still produces `InvalidUtf8` is the one that stopped clap.
(root: &clap::Command, argv: &'a [OsString])
| 332 | /// tokens; the first candidate that still produces `InvalidUtf8` is the one |
| 333 | /// that stopped clap. |
| 334 | fn rejected_non_utf8_arg<'a>(root: &clap::Command, argv: &'a [OsString]) -> Option<&'a OsStr> { |
| 335 | let indices = argv |
| 336 | .iter() |
| 337 | .enumerate() |
| 338 | .skip(1) |
| 339 | .filter_map(|(index, value)| value.to_str().is_none().then_some(index)) |
| 340 | .collect::<Vec<_>>(); |
| 341 | |
| 342 | for (position, index) in indices.iter().copied().enumerate() { |
| 343 | let mut probe = argv.to_vec(); |
| 344 | for later in indices.iter().copied().skip(position + 1) { |
| 345 | probe[later] = OsString::from("x"); |
| 346 | } |
| 347 | let mut command = root.clone(); |
| 348 | if matches!( |
| 349 | command.try_get_matches_from_mut(probe), |
| 350 | Err(error) if error.kind() == ErrorKind::InvalidUtf8 |
| 351 | ) { |
| 352 | return Some(argv[index].as_os_str()); |
| 353 | } |
| 354 | } |
| 355 | |
| 356 | indices.first().map(|index| argv[*index].as_os_str()) |
| 357 | } |
| 358 | |
| 359 | fn option_spellings(root: &clap::Command, key: &str, display: &str) -> Vec<String> { |
| 360 | let shown = display.split_whitespace().next().unwrap_or_default(); |