Skip to content

Commit fce7796

Browse files
authored
Merge pull request #3521 from epage/assert
fix(assert): Validate delimited defaults
2 parents 28162d4 + 3f2a370 commit fce7796

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/build/arg.rs

+6
Original file line numberDiff line numberDiff line change
@@ -4633,6 +4633,12 @@ impl<'help> Arg<'help> {
46334633
self.num_vals
46344634
}
46354635

4636+
/// Get the delimiter between multiple values
4637+
#[inline]
4638+
pub fn get_value_delimiter(&self) -> Option<char> {
4639+
self.val_delim
4640+
}
4641+
46364642
/// Get the index of this argument, if any
46374643
#[inline]
46384644
pub fn get_index(&self) -> Option<usize> {

src/build/debug_asserts.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::cmp::Ordering;
22

3+
use os_str_bytes::RawOsStr;
4+
35
use crate::build::arg::ArgProvider;
46
use crate::mkeymap::KeyType;
57
use crate::util::Id;
@@ -686,7 +688,16 @@ fn assert_defaults<'d>(
686688

687689
if let Some(validator) = arg.validator.as_ref() {
688690
let mut validator = validator.lock().unwrap();
689-
if let Err(err) = validator(default_s) {
691+
if let Some(delim) = arg.get_value_delimiter() {
692+
for part in default_s.split(delim) {
693+
if let Err(err) = validator(part) {
694+
panic!(
695+
"Argument `{}`'s {}={} failed validation: {}",
696+
arg.name, field, part, err
697+
);
698+
}
699+
}
700+
} else if let Err(err) = validator(default_s) {
690701
panic!(
691702
"Argument `{}`'s {}={} failed validation: {}",
692703
arg.name, field, default_s, err
@@ -697,7 +708,17 @@ fn assert_defaults<'d>(
697708

698709
if let Some(validator) = arg.validator_os.as_ref() {
699710
let mut validator = validator.lock().unwrap();
700-
if let Err(err) = validator(default_os) {
711+
if let Some(delim) = arg.get_value_delimiter() {
712+
let default_os = RawOsStr::new(default_os);
713+
for part in default_os.split(delim) {
714+
if let Err(err) = validator(&part.to_os_str()) {
715+
panic!(
716+
"Argument `{}`'s {}={:?} failed validation: {}",
717+
arg.name, field, part, err
718+
);
719+
}
720+
}
721+
} else if let Err(err) = validator(default_os) {
701722
panic!(
702723
"Argument `{}`'s {}={:?} failed validation: {}",
703724
arg.name, field, default_os, err

tests/builder/default_vals.rs

+35-3
Original file line numberDiff line numberDiff line change
@@ -648,15 +648,47 @@ fn default_values_are_possible_values() {
648648

649649
#[cfg(debug_assertions)]
650650
#[test]
651-
#[should_panic = "Argument `arg`'s default_value=value failed validation: invalid digit found in string"]
652-
fn default_values_are_valid() {
651+
#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"]
652+
fn invalid_default_values() {
653653
use clap::{Arg, Command};
654654

655655
let _ = Command::new("test")
656656
.arg(
657657
Arg::new("arg")
658658
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
659-
.default_value("value"),
659+
.default_value("one"),
660+
)
661+
.try_get_matches();
662+
}
663+
664+
#[test]
665+
fn valid_delimited_default_values() {
666+
use clap::{Arg, Command};
667+
668+
let _ = Command::new("test")
669+
.arg(
670+
Arg::new("arg")
671+
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
672+
.use_value_delimiter(true)
673+
.require_value_delimiter(true)
674+
.default_value("1,2,3"),
675+
)
676+
.try_get_matches();
677+
}
678+
679+
#[cfg(debug_assertions)]
680+
#[test]
681+
#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"]
682+
fn invalid_delimited_default_values() {
683+
use clap::{Arg, Command};
684+
685+
let _ = Command::new("test")
686+
.arg(
687+
Arg::new("arg")
688+
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
689+
.use_value_delimiter(true)
690+
.require_value_delimiter(true)
691+
.default_value("one,two"),
660692
)
661693
.try_get_matches();
662694
}

0 commit comments

Comments
 (0)