fix: Allow OsStr for some required_if_eq calls

This commit is contained in:
Ed Page 2022-08-16 10:22:24 -05:00
parent 3c2635adb2
commit 30d4ef4b09
3 changed files with 14 additions and 12 deletions

View file

@ -67,6 +67,7 @@ MSRV is now 1.60.0
- Changed the default type of `allow_external_subcommands` from `String` to `OsString`
- `Arg::default_missing_value` now applies per occurrence rather than if a value is missing across all occurrences
- `arg!(--long [value])` to accept `0..=1` per occurrence rather than across all occurrences, making it safe to use with `ArgAction::Append`
- Allow `OsStr`s for `Arg::{required_if_eq,required_if_eq_any,required_if_eq_all}`
- *(assert)* Always enforce that version is specified when the `ArgAction::Version` is used
- *(assert)* Add missing `#[track_caller]`s to make it easier to debug asserts
- *(assert)* Ensure `overrides_with` IDs are valid

View file

@ -1,13 +1,14 @@
// Std
#[cfg(feature = "env")]
use std::env;
use std::{
borrow::Cow,
cmp::{Ord, Ordering},
ffi::OsStr,
ffi::OsString,
fmt::{self, Display, Formatter},
str,
};
#[cfg(feature = "env")]
use std::{env, ffi::OsString};
// Internal
use super::{ArgFlags, ArgSettings};
@ -59,8 +60,8 @@ pub struct Arg<'help> {
pub(crate) overrides: Vec<Id>,
pub(crate) groups: Vec<Id>,
pub(crate) requires: Vec<(ArgPredicate<'help>, Id)>,
pub(crate) r_ifs: Vec<(Id, &'help str)>,
pub(crate) r_ifs_all: Vec<(Id, &'help str)>,
pub(crate) r_ifs: Vec<(Id, OsString)>,
pub(crate) r_ifs_all: Vec<(Id, OsString)>,
pub(crate) r_unless: Vec<Id>,
pub(crate) r_unless_all: Vec<Id>,
pub(crate) short: Option<char>,
@ -3038,8 +3039,8 @@ impl<'help> Arg<'help> {
/// [Conflicting]: Arg::conflicts_with()
/// [required]: Arg::required()
#[must_use]
pub fn required_if_eq(mut self, arg_id: impl Into<Id>, val: &'help str) -> Self {
self.r_ifs.push((arg_id.into(), val));
pub fn required_if_eq(mut self, arg_id: impl Into<Id>, val: impl Into<OsString>) -> Self {
self.r_ifs.push((arg_id.into(), val.into()));
self
}
@ -3119,10 +3120,10 @@ impl<'help> Arg<'help> {
#[must_use]
pub fn required_if_eq_any(
mut self,
ifs: impl IntoIterator<Item = (impl Into<Id>, &'help str)>,
ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsString>)>,
) -> Self {
self.r_ifs
.extend(ifs.into_iter().map(|(id, val)| (id.into(), val)));
.extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into())));
self
}
@ -3200,10 +3201,10 @@ impl<'help> Arg<'help> {
#[must_use]
pub fn required_if_eq_all(
mut self,
ifs: impl IntoIterator<Item = (impl Into<Id>, &'help str)>,
ifs: impl IntoIterator<Item = (impl Into<Id>, impl Into<OsString>)>,
) -> Self {
self.r_ifs_all
.extend(ifs.into_iter().map(|(id, val)| (id.into(), val)));
.extend(ifs.into_iter().map(|(id, val)| (id.into(), val.into())));
self
}

View file

@ -281,7 +281,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
// Validate the conditionally required args
for a in self.cmd.get_arguments() {
for (other, val) in &a.r_ifs {
if matcher.check_explicit(other, &ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
if matcher.check_explicit(other, &ArgPredicate::Equals(val.as_os_str()))
&& !matcher.check_explicit(&a.id, &ArgPredicate::IsPresent)
{
return self.missing_required_error(matcher, vec![a.id.clone()]);
@ -289,7 +289,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
}
let match_all = a.r_ifs_all.iter().all(|(other, val)| {
matcher.check_explicit(other, &ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
matcher.check_explicit(other, &ArgPredicate::Equals(val.as_os_str()))
});
if match_all
&& !a.r_ifs_all.is_empty()