]> git.proxmox.com Git - rustc.git/blob - vendor/clap/src/builder/debug_asserts.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / vendor / clap / src / builder / debug_asserts.rs
1 use std::cmp::Ordering;
2
3 use clap_lex::RawOsStr;
4
5 use crate::builder::arg::ArgProvider;
6 use crate::mkeymap::KeyType;
7 use crate::ArgAction;
8 use crate::{Arg, Command, ValueHint};
9
10 pub(crate) fn assert_app(cmd: &Command) {
11 debug!("Command::_debug_asserts");
12
13 let mut short_flags = vec![];
14 let mut long_flags = vec![];
15
16 // Invalid version flag settings
17 if cmd.get_version().is_none() && cmd.get_long_version().is_none() {
18 // PropagateVersion is meaningless if there is no version
19 assert!(
20 !cmd.is_propagate_version_set(),
21 "Command {}: No version information via Command::version or Command::long_version to propagate",
22 cmd.get_name(),
23 );
24
25 // Used `Command::mut_arg("version", ..) but did not provide any version information to display
26 let version_needed = cmd
27 .get_arguments()
28 .filter(|x| {
29 let action_set = matches!(x.get_action(), ArgAction::Version);
30 #[cfg(not(feature = "unstable-v4"))]
31 let provider_set = matches!(x.provider, ArgProvider::GeneratedMutated);
32 #[cfg(feature = "unstable-v4")]
33 let provider_set = matches!(
34 x.provider,
35 ArgProvider::User | ArgProvider::GeneratedMutated
36 );
37 action_set && provider_set
38 })
39 .map(|x| x.get_id())
40 .collect::<Vec<_>>();
41
42 assert_eq!(version_needed, Vec::<&str>::new(), "Command {}: `ArgAction::Version` used without providing Command::version or Command::long_version"
43 ,cmd.get_name()
44 );
45 }
46
47 for sc in cmd.get_subcommands() {
48 if let Some(s) = sc.get_short_flag().as_ref() {
49 short_flags.push(Flag::Command(format!("-{}", s), sc.get_name()));
50 }
51
52 for short_alias in sc.get_all_short_flag_aliases() {
53 short_flags.push(Flag::Command(format!("-{}", short_alias), sc.get_name()));
54 }
55
56 if let Some(l) = sc.get_long_flag().as_ref() {
57 #[cfg(feature = "unstable-v4")]
58 {
59 assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
60 }
61 long_flags.push(Flag::Command(format!("--{}", l), sc.get_name()));
62 }
63
64 for long_alias in sc.get_all_long_flag_aliases() {
65 long_flags.push(Flag::Command(format!("--{}", long_alias), sc.get_name()));
66 }
67 }
68
69 for arg in cmd.get_arguments() {
70 assert_arg(arg);
71
72 assert!(
73 !cmd.is_multicall_set(),
74 "Command {}: Arguments like {} cannot be set on a multicall command",
75 cmd.get_name(),
76 arg.name
77 );
78
79 if let Some(s) = arg.short.as_ref() {
80 short_flags.push(Flag::Arg(format!("-{}", s), &*arg.name));
81 }
82
83 for (short_alias, _) in &arg.short_aliases {
84 short_flags.push(Flag::Arg(format!("-{}", short_alias), arg.name));
85 }
86
87 if let Some(l) = arg.long.as_ref() {
88 #[cfg(feature = "unstable-v4")]
89 {
90 assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.name, l);
91 }
92 long_flags.push(Flag::Arg(format!("--{}", l), &*arg.name));
93 }
94
95 for (long_alias, _) in &arg.aliases {
96 long_flags.push(Flag::Arg(format!("--{}", long_alias), arg.name));
97 }
98
99 // Name conflicts
100 assert!(
101 cmd.two_args_of(|x| x.id == arg.id).is_none(),
102 "Command {}: Argument names must be unique, but '{}' is in use by more than one argument or group",
103 cmd.get_name(),
104 arg.name,
105 );
106
107 // Long conflicts
108 if let Some(l) = arg.long {
109 if let Some((first, second)) = cmd.two_args_of(|x| x.long == Some(l)) {
110 panic!(
111 "Command {}: Long option names must be unique for each argument, \
112 but '--{}' is in use by both '{}' and '{}'",
113 cmd.get_name(),
114 l,
115 first.name,
116 second.name
117 )
118 }
119 }
120
121 // Short conflicts
122 if let Some(s) = arg.short {
123 if let Some((first, second)) = cmd.two_args_of(|x| x.short == Some(s)) {
124 panic!(
125 "Command {}: Short option names must be unique for each argument, \
126 but '-{}' is in use by both '{}' and '{}'",
127 cmd.get_name(),
128 s,
129 first.name,
130 second.name
131 )
132 }
133 }
134
135 // Index conflicts
136 if let Some(idx) = arg.index {
137 if let Some((first, second)) =
138 cmd.two_args_of(|x| x.is_positional() && x.index == Some(idx))
139 {
140 panic!(
141 "Command {}: Argument '{}' has the same index as '{}' \
142 and they are both positional arguments\n\n\t \
143 Use Arg::multiple_values(true) to allow one \
144 positional argument to take multiple values",
145 cmd.get_name(),
146 first.name,
147 second.name
148 )
149 }
150 }
151
152 // requires, r_if, r_unless
153 for req in &arg.requires {
154 assert!(
155 cmd.id_exists(&req.1),
156 "Command {}: Argument or group '{:?}' specified in 'requires*' for '{}' does not exist",
157 cmd.get_name(),
158 req.1,
159 arg.name,
160 );
161 }
162
163 for req in &arg.r_ifs {
164 #[cfg(feature = "unstable-v4")]
165 {
166 assert!(
167 !arg.is_required_set(),
168 "Argument {}: `required` conflicts with `required_if_eq*`",
169 arg.name
170 );
171 }
172 assert!(
173 cmd.id_exists(&req.0),
174 "Command {}: Argument or group '{:?}' specified in 'required_if_eq*' for '{}' does not exist",
175 cmd.get_name(),
176 req.0,
177 arg.name
178 );
179 }
180
181 for req in &arg.r_ifs_all {
182 #[cfg(feature = "unstable-v4")]
183 {
184 assert!(
185 !arg.is_required_set(),
186 "Argument {}: `required` conflicts with `required_if_eq_all`",
187 arg.name
188 );
189 }
190 assert!(
191 cmd.id_exists(&req.0),
192 "Command {}: Argument or group '{:?}' specified in 'required_if_eq_all' for '{}' does not exist",
193 cmd.get_name(),
194 req.0,
195 arg.name
196 );
197 }
198
199 for req in &arg.r_unless {
200 #[cfg(feature = "unstable-v4")]
201 {
202 assert!(
203 !arg.is_required_set(),
204 "Argument {}: `required` conflicts with `required_unless*`",
205 arg.name
206 );
207 }
208 assert!(
209 cmd.id_exists(req),
210 "Command {}: Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist",
211 cmd.get_name(),
212 req,
213 arg.name,
214 );
215 }
216
217 for req in &arg.r_unless_all {
218 #[cfg(feature = "unstable-v4")]
219 {
220 assert!(
221 !arg.is_required_set(),
222 "Argument {}: `required` conflicts with `required_unless*`",
223 arg.name
224 );
225 }
226 assert!(
227 cmd.id_exists(req),
228 "Command {}: Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist",
229 cmd.get_name(),
230 req,
231 arg.name,
232 );
233 }
234
235 // blacklist
236 for req in &arg.blacklist {
237 assert!(
238 cmd.id_exists(req),
239 "Command {}: Argument or group '{:?}' specified in 'conflicts_with*' for '{}' does not exist",
240 cmd.get_name(),
241 req,
242 arg.name,
243 );
244 }
245
246 if arg.is_last_set() {
247 assert!(
248 arg.long.is_none(),
249 "Command {}: Flags or Options cannot have last(true) set. '{}' has both a long and last(true) set.",
250 cmd.get_name(),
251 arg.name
252 );
253 assert!(
254 arg.short.is_none(),
255 "Command {}: Flags or Options cannot have last(true) set. '{}' has both a short and last(true) set.",
256 cmd.get_name(),
257 arg.name
258 );
259 }
260
261 assert!(
262 !(arg.is_required_set() && arg.is_global_set()),
263 "Command {}: Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
264 cmd.get_name(),
265 arg.name
266 );
267
268 // validators
269 assert!(
270 arg.validator.is_none() || arg.validator_os.is_none(),
271 "Command {}: Argument '{}' has both `validator` and `validator_os` set which is not allowed",
272 cmd.get_name(),
273 arg.name
274 );
275
276 if arg.get_value_hint() == ValueHint::CommandWithArguments {
277 assert!(
278 arg.is_positional(),
279 "Command {}: Argument '{}' has hint CommandWithArguments and must be positional.",
280 cmd.get_name(),
281 arg.name
282 );
283
284 assert!(
285 cmd.is_trailing_var_arg_set(),
286 "Command {}: Positional argument '{}' has hint CommandWithArguments, so Command must have TrailingVarArg set.",
287 cmd.get_name(),
288 arg.name
289 );
290 }
291 }
292
293 for group in cmd.get_groups() {
294 // Name conflicts
295 assert!(
296 cmd.get_groups().filter(|x| x.id == group.id).count() < 2,
297 "Command {}: Argument group name must be unique\n\n\t'{}' is already in use",
298 cmd.get_name(),
299 group.name,
300 );
301
302 // Groups should not have naming conflicts with Args
303 assert!(
304 !cmd.get_arguments().any(|x| x.id == group.id),
305 "Command {}: Argument group name '{}' must not conflict with argument name",
306 cmd.get_name(),
307 group.name,
308 );
309
310 for arg in &group.args {
311 // Args listed inside groups should exist
312 assert!(
313 cmd.get_arguments().any(|x| x.id == *arg),
314 "Command {}: Argument group '{}' contains non-existent argument '{:?}'",
315 cmd.get_name(),
316 group.name,
317 arg
318 );
319 }
320 }
321
322 // Conflicts between flags and subcommands
323
324 long_flags.sort_unstable();
325 short_flags.sort_unstable();
326
327 detect_duplicate_flags(&long_flags, "long");
328 detect_duplicate_flags(&short_flags, "short");
329
330 _verify_positionals(cmd);
331
332 if let Some(help_template) = cmd.get_help_template() {
333 assert!(
334 !help_template.contains("{flags}"),
335 "Command {}: {}",
336 cmd.get_name(),
337 "`{flags}` template variable was removed in clap3, they are now included in `{options}`",
338 );
339 assert!(
340 !help_template.contains("{unified}"),
341 "Command {}: {}",
342 cmd.get_name(),
343 "`{unified}` template variable was removed in clap3, use `{options}` instead"
344 );
345 }
346
347 cmd._panic_on_missing_help(cmd.is_help_expected_set());
348 assert_app_flags(cmd);
349 }
350
351 #[derive(Eq)]
352 enum Flag<'a> {
353 Command(String, &'a str),
354 Arg(String, &'a str),
355 }
356
357 impl PartialEq for Flag<'_> {
358 fn eq(&self, other: &Flag) -> bool {
359 self.cmp(other) == Ordering::Equal
360 }
361 }
362
363 impl PartialOrd for Flag<'_> {
364 fn partial_cmp(&self, other: &Flag) -> Option<Ordering> {
365 use Flag::*;
366
367 match (self, other) {
368 (Command(s1, _), Command(s2, _))
369 | (Arg(s1, _), Arg(s2, _))
370 | (Command(s1, _), Arg(s2, _))
371 | (Arg(s1, _), Command(s2, _)) => {
372 if s1 == s2 {
373 Some(Ordering::Equal)
374 } else {
375 s1.partial_cmp(s2)
376 }
377 }
378 }
379 }
380 }
381
382 impl Ord for Flag<'_> {
383 fn cmp(&self, other: &Self) -> Ordering {
384 self.partial_cmp(other).unwrap()
385 }
386 }
387
388 fn detect_duplicate_flags(flags: &[Flag], short_or_long: &str) {
389 use Flag::*;
390
391 for (one, two) in find_duplicates(flags) {
392 match (one, two) {
393 (Command(flag, one), Command(_, another)) if one != another => panic!(
394 "the '{}' {} flag is specified for both '{}' and '{}' subcommands",
395 flag, short_or_long, one, another
396 ),
397
398 (Arg(flag, one), Arg(_, another)) if one != another => panic!(
399 "{} option names must be unique, but '{}' is in use by both '{}' and '{}'",
400 short_or_long, flag, one, another
401 ),
402
403 (Arg(flag, arg), Command(_, sub)) | (Command(flag, sub), Arg(_, arg)) => panic!(
404 "the '{}' {} flag for the '{}' argument conflicts with the short flag \
405 for '{}' subcommand",
406 flag, short_or_long, arg, sub
407 ),
408
409 _ => {}
410 }
411 }
412 }
413
414 /// Find duplicates in a sorted array.
415 ///
416 /// The algorithm is simple: the array is sorted, duplicates
417 /// must be placed next to each other, we can check only adjacent elements.
418 fn find_duplicates<T: PartialEq>(slice: &[T]) -> impl Iterator<Item = (&T, &T)> {
419 slice.windows(2).filter_map(|w| {
420 if w[0] == w[1] {
421 Some((&w[0], &w[1]))
422 } else {
423 None
424 }
425 })
426 }
427
428 fn assert_app_flags(cmd: &Command) {
429 macro_rules! checker {
430 ($a:ident requires $($b:ident)|+) => {
431 if cmd.$a() {
432 let mut s = String::new();
433
434 $(
435 if !cmd.$b() {
436 s.push_str(&format!(" AppSettings::{} is required when AppSettings::{} is set.\n", std::stringify!($b), std::stringify!($a)));
437 }
438 )+
439
440 if !s.is_empty() {
441 panic!("{}", s)
442 }
443 }
444 };
445 ($a:ident conflicts $($b:ident)|+) => {
446 if cmd.$a() {
447 let mut s = String::new();
448
449 $(
450 if cmd.$b() {
451 s.push_str(&format!(" AppSettings::{} conflicts with AppSettings::{}.\n", std::stringify!($b), std::stringify!($a)));
452 }
453 )+
454
455 if !s.is_empty() {
456 panic!("{}\n{}", cmd.get_name(), s)
457 }
458 }
459 };
460 }
461
462 checker!(is_allow_invalid_utf8_for_external_subcommands_set requires is_allow_external_subcommands_set);
463 checker!(is_multicall_set conflicts is_no_binary_name_set);
464 }
465
466 #[cfg(debug_assertions)]
467 fn _verify_positionals(cmd: &Command) -> bool {
468 debug!("Command::_verify_positionals");
469 // Because you must wait until all arguments have been supplied, this is the first chance
470 // to make assertions on positional argument indexes
471 //
472 // First we verify that the index highest supplied index, is equal to the number of
473 // positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
474 // but no 2)
475
476 let highest_idx = cmd
477 .get_keymap()
478 .keys()
479 .filter_map(|x| {
480 if let KeyType::Position(n) = x {
481 Some(*n)
482 } else {
483 None
484 }
485 })
486 .max()
487 .unwrap_or(0);
488
489 let num_p = cmd.get_keymap().keys().filter(|x| x.is_position()).count();
490
491 assert!(
492 highest_idx == num_p,
493 "Found positional argument whose index is {} but there \
494 are only {} positional arguments defined",
495 highest_idx,
496 num_p
497 );
498
499 // Next we verify that only the highest index has takes multiple arguments (if any)
500 let only_highest = |a: &Arg| a.is_multiple() && (a.index.unwrap_or(0) != highest_idx);
501 if cmd.get_positionals().any(only_highest) {
502 // First we make sure if there is a positional that allows multiple values
503 // the one before it (second to last) has one of these:
504 // * a value terminator
505 // * ArgSettings::Last
506 // * The last arg is Required
507
508 // We can't pass the closure (it.next()) to the macro directly because each call to
509 // find() (iterator, not macro) gets called repeatedly.
510 let last = &cmd.get_keymap()[&KeyType::Position(highest_idx)];
511 let second_to_last = &cmd.get_keymap()[&KeyType::Position(highest_idx - 1)];
512
513 // Either the final positional is required
514 // Or the second to last has a terminator or .last(true) set
515 let ok = last.is_required_set()
516 || (second_to_last.terminator.is_some() || second_to_last.is_last_set())
517 || last.is_last_set();
518 assert!(
519 ok,
520 "When using a positional argument with .multiple_values(true) that is *not the \
521 last* positional argument, the last positional argument (i.e. the one \
522 with the highest index) *must* have .required(true) or .last(true) set."
523 );
524
525 // We make sure if the second to last is Multiple the last is ArgSettings::Last
526 let ok = second_to_last.is_multiple() || last.is_last_set();
527 assert!(
528 ok,
529 "Only the last positional argument, or second to last positional \
530 argument may be set to .multiple_values(true)"
531 );
532
533 // Next we check how many have both Multiple and not a specific number of values set
534 let count = cmd
535 .get_positionals()
536 .filter(|p| {
537 #[allow(deprecated)]
538 {
539 p.is_multiple_occurrences_set()
540 || (p.is_multiple_values_set() && p.num_vals.is_none())
541 }
542 })
543 .count();
544 let ok = count <= 1
545 || (last.is_last_set()
546 && last.is_multiple()
547 && second_to_last.is_multiple()
548 && count == 2);
549 assert!(
550 ok,
551 "Only one positional argument with .multiple_values(true) set is allowed per \
552 command, unless the second one also has .last(true) set"
553 );
554 }
555
556 let mut found = false;
557
558 if cmd.is_allow_missing_positional_set() {
559 // Check that if a required positional argument is found, all positions with a lower
560 // index are also required.
561 let mut foundx2 = false;
562
563 for p in cmd.get_positionals() {
564 if foundx2 && !p.is_required_set() {
565 assert!(
566 p.is_required_set(),
567 "Found non-required positional argument with a lower \
568 index than a required positional argument by two or more: {:?} \
569 index {:?}",
570 p.name,
571 p.index
572 );
573 } else if p.is_required_set() && !p.is_last_set() {
574 // Args that .last(true) don't count since they can be required and have
575 // positionals with a lower index that aren't required
576 // Imagine: prog <req1> [opt1] -- <req2>
577 // Both of these are valid invocations:
578 // $ prog r1 -- r2
579 // $ prog r1 o1 -- r2
580 if found {
581 foundx2 = true;
582 continue;
583 }
584 found = true;
585 continue;
586 } else {
587 found = false;
588 }
589 }
590 } else {
591 // Check that if a required positional argument is found, all positions with a lower
592 // index are also required
593 for p in (1..=num_p).rev().filter_map(|n| cmd.get_keymap().get(&n)) {
594 if found {
595 assert!(
596 p.is_required_set(),
597 "Found non-required positional argument with a lower \
598 index than a required positional argument: {:?} index {:?}",
599 p.name,
600 p.index
601 );
602 } else if p.is_required_set() && !p.is_last_set() {
603 // Args that .last(true) don't count since they can be required and have
604 // positionals with a lower index that aren't required
605 // Imagine: prog <req1> [opt1] -- <req2>
606 // Both of these are valid invocations:
607 // $ prog r1 -- r2
608 // $ prog r1 o1 -- r2
609 found = true;
610 continue;
611 }
612 }
613 }
614 assert!(
615 cmd.get_positionals().filter(|p| p.is_last_set()).count() < 2,
616 "Only one positional argument may have last(true) set. Found two."
617 );
618 if cmd
619 .get_positionals()
620 .any(|p| p.is_last_set() && p.is_required_set())
621 && cmd.has_subcommands()
622 && !cmd.is_subcommand_negates_reqs_set()
623 {
624 panic!(
625 "Having a required positional argument with .last(true) set *and* child \
626 subcommands without setting SubcommandsNegateReqs isn't compatible."
627 );
628 }
629
630 true
631 }
632
633 fn assert_arg(arg: &Arg) {
634 debug!("Arg::_debug_asserts:{}", arg.name);
635
636 // Self conflict
637 // TODO: this check should be recursive
638 assert!(
639 !arg.blacklist.iter().any(|x| *x == arg.id),
640 "Argument '{}' cannot conflict with itself",
641 arg.name,
642 );
643
644 assert_eq!(
645 arg.get_action().takes_values(),
646 arg.is_takes_value_set(),
647 "Argument `{}`'s selected action {:?} contradicts `takes_value`",
648 arg.name,
649 arg.get_action()
650 );
651 if let Some(action_type_id) = arg.get_action().value_type_id() {
652 assert_eq!(
653 action_type_id,
654 arg.get_value_parser().type_id(),
655 "Argument `{}`'s selected action {:?} contradicts `value_parser` ({:?})",
656 arg.name,
657 arg.get_action(),
658 arg.get_value_parser()
659 );
660 }
661
662 if arg.get_value_hint() != ValueHint::Unknown {
663 assert!(
664 arg.is_takes_value_set(),
665 "Argument '{}' has value hint but takes no value",
666 arg.name
667 );
668
669 if arg.get_value_hint() == ValueHint::CommandWithArguments {
670 assert!(
671 arg.is_multiple_values_set(),
672 "Argument '{}' uses hint CommandWithArguments and must accept multiple values",
673 arg.name
674 )
675 }
676 }
677
678 if arg.index.is_some() {
679 assert!(
680 arg.is_positional(),
681 "Argument '{}' is a positional argument and can't have short or long name versions",
682 arg.name
683 );
684 assert!(
685 arg.is_takes_value_set(),
686 "Argument '{}` is positional, it must take a value",
687 arg.name
688 );
689 }
690
691 #[cfg(feature = "unstable-v4")]
692 {
693 let num_vals = arg.get_num_vals().unwrap_or(usize::MAX);
694 let num_val_names = arg.get_value_names().unwrap_or(&[]).len();
695 if num_vals < num_val_names {
696 panic!(
697 "Argument {}: Too many value names ({}) compared to number_of_values ({})",
698 arg.name, num_val_names, num_vals
699 );
700 }
701 }
702
703 assert_arg_flags(arg);
704
705 assert_defaults(arg, "default_value", arg.default_vals.iter().copied());
706 assert_defaults(
707 arg,
708 "default_missing_value",
709 arg.default_missing_vals.iter().copied(),
710 );
711 assert_defaults(
712 arg,
713 "default_value_if",
714 arg.default_vals_ifs
715 .iter()
716 .filter_map(|(_, _, default)| *default),
717 );
718 }
719
720 fn assert_arg_flags(arg: &Arg) {
721 macro_rules! checker {
722 ($a:ident requires $($b:ident)|+) => {
723 if arg.$a() {
724 let mut s = String::new();
725
726 $(
727 if !arg.$b() {
728 s.push_str(&format!(" Arg::{} is required when Arg::{} is set.\n", std::stringify!($b), std::stringify!($a)));
729 }
730 )+
731
732 if !s.is_empty() {
733 panic!("Argument {:?}\n{}", arg.get_id(), s)
734 }
735 }
736 }
737 }
738
739 checker!(is_require_value_delimiter_set requires is_takes_value_set);
740 checker!(is_require_value_delimiter_set requires is_use_value_delimiter_set);
741 checker!(is_hide_possible_values_set requires is_takes_value_set);
742 checker!(is_allow_hyphen_values_set requires is_takes_value_set);
743 checker!(is_require_equals_set requires is_takes_value_set);
744 checker!(is_last_set requires is_takes_value_set);
745 checker!(is_hide_default_value_set requires is_takes_value_set);
746 checker!(is_multiple_values_set requires is_takes_value_set);
747 checker!(is_ignore_case_set requires is_takes_value_set);
748 {
749 #![allow(deprecated)]
750 checker!(is_forbid_empty_values_set requires is_takes_value_set);
751 checker!(is_allow_invalid_utf8_set requires is_takes_value_set);
752 }
753 }
754
755 fn assert_defaults<'d>(
756 arg: &Arg,
757 field: &'static str,
758 defaults: impl IntoIterator<Item = &'d std::ffi::OsStr>,
759 ) {
760 for default_os in defaults {
761 if let Some(default_s) = default_os.to_str() {
762 if !arg.possible_vals.is_empty() {
763 if let Some(delim) = arg.get_value_delimiter() {
764 for part in default_s.split(delim) {
765 assert!(
766 arg.possible_vals.iter().any(|possible_val| {
767 possible_val.matches(part, arg.is_ignore_case_set())
768 }),
769 "Argument `{}`'s {}={} doesn't match possible values",
770 arg.name,
771 field,
772 part
773 )
774 }
775 } else {
776 assert!(
777 arg.possible_vals.iter().any(|possible_val| {
778 possible_val.matches(default_s, arg.is_ignore_case_set())
779 }),
780 "Argument `{}`'s {}={} doesn't match possible values",
781 arg.name,
782 field,
783 default_s
784 );
785 }
786 }
787
788 if let Some(validator) = arg.validator.as_ref() {
789 let mut validator = validator.lock().unwrap();
790 if let Some(delim) = arg.get_value_delimiter() {
791 for part in default_s.split(delim) {
792 if let Err(err) = validator(part) {
793 panic!(
794 "Argument `{}`'s {}={} failed validation: {}",
795 arg.name, field, part, err
796 );
797 }
798 }
799 } else if let Err(err) = validator(default_s) {
800 panic!(
801 "Argument `{}`'s {}={} failed validation: {}",
802 arg.name, field, default_s, err
803 );
804 }
805 }
806 }
807
808 if let Some(validator) = arg.validator_os.as_ref() {
809 let mut validator = validator.lock().unwrap();
810 if let Some(delim) = arg.get_value_delimiter() {
811 let default_os = RawOsStr::new(default_os);
812 for part in default_os.split(delim) {
813 if let Err(err) = validator(&part.to_os_str()) {
814 panic!(
815 "Argument `{}`'s {}={:?} failed validation: {}",
816 arg.name, field, part, err
817 );
818 }
819 }
820 } else if let Err(err) = validator(default_os) {
821 panic!(
822 "Argument `{}`'s {}={:?} failed validation: {}",
823 arg.name, field, default_os, err
824 );
825 }
826 }
827
828 let value_parser = arg.get_value_parser();
829 let assert_cmd = Command::new("assert");
830 if let Some(delim) = arg.get_value_delimiter() {
831 let default_os = RawOsStr::new(default_os);
832 for part in default_os.split(delim) {
833 if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), &part.to_os_str())
834 {
835 panic!(
836 "Argument `{}`'s {}={:?} failed validation: {}",
837 arg.name,
838 field,
839 part.to_str_lossy(),
840 err
841 );
842 }
843 }
844 } else if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), default_os) {
845 panic!(
846 "Argument `{}`'s {}={:?} failed validation: {}",
847 arg.name, field, default_os, err
848 );
849 }
850 }
851 }