1821: Make debug output show names of args along with hashes r=pksunkara a=CreepySkeleton



Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
This commit is contained in:
bors[bot] 2020-04-14 21:16:52 +00:00 committed by GitHub
commit d210b9fced
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 411 additions and 325 deletions

View file

@ -24,13 +24,11 @@ use crate::output::fmt::ColorWhen;
use crate::output::{Help, Usage};
use crate::parse::errors::Result as ClapResult;
use crate::parse::{ArgMatcher, ArgMatches, Input, Parser};
use crate::util::{Key, HELP_HASH, VERSION_HASH};
use crate::util::{Id, Key};
use crate::INTERNAL_ERROR_MSG;
type Id = u64;
// FIXME (@CreepySkeleton): some of this variants are never constructed
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[allow(unused)]
pub(crate) enum Propagation {
To(Id),
@ -195,9 +193,8 @@ impl<'b> App<'b> {
/// ```
pub fn new<S: Into<String>>(n: S) -> Self {
let name = n.into();
let id = name.key();
App {
id,
id: Id::from(&*name),
name,
disp_ord: 999,
..Default::default()
@ -1060,10 +1057,11 @@ impl<'b> App<'b> {
F: FnOnce(Arg<'b>) -> Arg<'b>,
T: Key + Into<&'b str>,
{
let id = arg_id.key();
let a = self.args.remove_by_name(id).unwrap_or_else(|| Arg {
let arg_id: &str = arg_id.into();
let id = Id::from(arg_id);
let a = self.args.remove_by_name(&id).unwrap_or_else(|| Arg {
id,
name: arg_id.into(),
name: arg_id,
..Arg::default()
});
self.args.push(f(a));
@ -1470,7 +1468,7 @@ impl<'b> App<'b> {
.args
.iter()
.filter(|a| a.global)
.map(|ga| ga.id)
.map(|ga| ga.id.clone())
.collect();
matcher.propagate_globals(&global_arg_vec);
@ -1484,7 +1482,7 @@ impl<'b> App<'b> {
debugln!("App::_build;");
#[cfg(all(feature = "color", windows))]
ansi_term::enable_ansi_support();
let _ = ansi_term::enable_ansi_support();
// Make sure all the globally set flags apply to us as well
self.settings = self.settings | self.g_settings;
@ -1496,15 +1494,15 @@ impl<'b> App<'b> {
for a in self.args.args.iter_mut() {
// Fill in the groups
if let Some(ref grps) = a.groups {
for &g in grps {
for g in grps {
let mut found = false;
if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == g) {
ag.args.push(a.id);
if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == *g) {
ag.args.push(a.id.clone());
found = true;
}
if !found {
let mut ag = ArgGroup::_with_id(g);
ag.args.push(a.id);
let mut ag = ArgGroup::_with_id(g.clone());
ag.args.push(a.id.clone());
self.groups.push(ag);
}
}
@ -1732,7 +1730,7 @@ impl<'b> App<'b> {
for sc in &mut self.subcommands {
propagate_subcmd!(self, sc);
if prop == Propagation::Full {
sc._propagate(prop);
sc._propagate(prop.clone());
}
}
}
@ -1754,7 +1752,7 @@ impl<'b> App<'b> {
.args
.args
.iter()
.any(|x| x.long == Some("help") || x.id == HELP_HASH))
.any(|x| x.long == Some("help") || x.id == Id::help_hash()))
{
debugln!("App::_create_help_and_version: Building --help");
let mut help = Arg::with_name("help")
@ -1770,7 +1768,7 @@ impl<'b> App<'b> {
.args
.args
.iter()
.any(|x| x.long == Some("version") || x.id == VERSION_HASH)
.any(|x| x.long == Some("version") || x.id == Id::version_hash())
|| self.is_set(AppSettings::DisableVersion))
{
debugln!("App::_create_help_and_version: Building --version");
@ -1785,7 +1783,7 @@ impl<'b> App<'b> {
}
if self.has_subcommands()
&& !self.is_set(AppSettings::DisableHelpSubcommand)
&& !self.subcommands.iter().any(|s| s.id == HELP_HASH)
&& !self.subcommands.iter().any(|s| s.id == Id::help_hash())
{
debugln!("App::_create_help_and_version: Building help");
self.subcommands.push(
@ -1874,11 +1872,11 @@ impl<'b> App<'b> {
}
}
pub(crate) fn format_group(&self, g: Id) -> String {
pub(crate) fn format_group(&self, g: &Id) -> String {
let g_string = self
.unroll_args_in_group(g)
.iter()
.filter_map(|&x| self.find(x))
.filter_map(|x| self.find(x))
.map(|x| {
if x.index.is_some() {
x.name.to_owned()
@ -1894,8 +1892,8 @@ impl<'b> App<'b> {
// Internal Query Methods
impl<'b> App<'b> {
pub(crate) fn find(&self, arg_id: Id) -> Option<&Arg<'b>> {
self.args.args.iter().find(|a| a.id == arg_id)
pub(crate) fn find(&self, arg_id: &Id) -> Option<&Arg<'b>> {
self.args.args.iter().find(|a| a.id == *arg_id)
}
// Should we color the output? None=determined by output location, true=yes, false=no
@ -1949,22 +1947,22 @@ impl<'b> App<'b> {
.any(|sc| !sc.is_set(AppSettings::Hidden))
}
pub(crate) fn unroll_args_in_group(&self, group: Id) -> Vec<Id> {
pub(crate) fn unroll_args_in_group(&self, group: &Id) -> Vec<Id> {
let mut g_vec = vec![group];
let mut args = vec![];
while let Some(ref g) = g_vec.pop() {
for &n in self
for n in self
.groups
.iter()
.find(|grp| &grp.id == g)
.find(|grp| grp.id == **g)
.expect(INTERNAL_ERROR_MSG)
.args
.iter()
{
if !args.contains(&n) {
if !args.contains(n) {
if self.find(n).is_some() {
args.push(n)
args.push(n.clone())
} else {
g_vec.push(n);
}
@ -1975,20 +1973,20 @@ impl<'b> App<'b> {
args
}
pub(crate) fn unroll_requirements_for_arg(&self, arg: Id, matcher: &ArgMatcher) -> Vec<Id> {
let requires_if_or_not = |&(val, req_arg)| {
pub(crate) fn unroll_requirements_for_arg(&self, arg: &Id, matcher: &ArgMatcher) -> Vec<Id> {
let requires_if_or_not = |(val, req_arg): &(Option<&str>, Id)| -> Option<Id> {
if let Some(v) = val {
if matcher
.get(arg)
.map(|ma| ma.contains_val(v))
.unwrap_or(false)
{
Some(req_arg)
Some(req_arg.clone())
} else {
None
}
} else {
Some(req_arg)
Some(req_arg.clone())
}
};
@ -2006,9 +2004,9 @@ impl<'b> App<'b> {
if let Some(arg) = self.find(a) {
if let Some(ref reqs) = arg.requires {
for r in reqs.iter().filter_map(requires_if_or_not) {
if let Some(req) = self.find(r) {
if let Some(req) = self.find(&r) {
if req.requires.is_some() {
r_vec.push(req.id)
r_vec.push(&req.id)
}
}
args.push(r);

View file

@ -20,16 +20,14 @@ use crate::util::VecMap;
// Internal
use crate::build::{arg::settings::ArgFlags, usage_parser::UsageParser};
use crate::util::Key;
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
use crate::util::OsStrExt3;
use crate::util::{Id, Key};
use crate::INTERNAL_ERROR_MSG;
type Validator = Rc<dyn Fn(String) -> Result<(), String>>;
type ValidatorOs = Rc<dyn Fn(&OsStr) -> Result<(), String>>;
type Id = u64;
/// The abstract representation of a command line argument. Used to set all the options and
/// relationships that define a valid argument for the program.
///
@ -129,9 +127,9 @@ impl<'help> Arg<'help> {
impl<'help> Arg<'help> {
/// @TODO @p2 @docs @v3-beta1: Write Docs
pub fn new<T: Key>(t: T) -> Self {
pub fn new<T: Key + ToString>(t: T) -> Self {
Arg {
id: t.key(),
id: t.into(),
disp_ord: 999,
unified_ord: 999,
..Default::default()
@ -157,7 +155,7 @@ impl<'help> Arg<'help> {
/// [`Arg`]: ./struct.Arg.html
pub fn with_name(n: &'help str) -> Self {
Arg {
id: n.key(),
id: n.into(),
name: n,
disp_ord: 999,
unified_ord: 999,
@ -626,11 +624,11 @@ impl<'help> Arg<'help> {
/// [`Arg::required`]: ./struct.Arg.html#method.required
/// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless
pub fn required_unless<T: Key>(mut self, arg_id: T) -> Self {
let name = arg_id.key();
let id = arg_id.into();
if let Some(ref mut vec) = self.r_unless {
vec.push(name);
vec.push(id);
} else {
self.r_unless = Some(vec![name]);
self.r_unless = Some(vec![id]);
}
self
}
@ -701,10 +699,10 @@ impl<'help> Arg<'help> {
pub fn required_unless_all(mut self, names: &[&str]) -> Self {
if let Some(ref mut vec) = self.r_unless {
for s in names {
vec.push(s.key());
vec.push(s.into());
}
} else {
self.r_unless = Some(names.iter().map(Key::key).collect());
self.r_unless = Some(names.iter().map(Into::into).collect());
}
self.setting(ArgSettings::RequiredUnlessAll)
}
@ -776,10 +774,10 @@ impl<'help> Arg<'help> {
pub fn required_unless_one(mut self, names: &[&str]) -> Self {
if let Some(ref mut vec) = self.r_unless {
for s in names {
vec.push(s.key());
vec.push(s.into());
}
} else {
self.r_unless = Some(names.iter().map(Key::key).collect());
self.r_unless = Some(names.iter().map(Into::into).collect());
}
self
}
@ -830,7 +828,7 @@ impl<'help> Arg<'help> {
/// [`Arg::exclusive(true)`]: ./struct.Arg.html#method.exclusive
pub fn conflicts_with<T: Key>(mut self, arg_id: T) -> Self {
let name = arg_id.key();
let name = arg_id.into();
if let Some(ref mut vec) = self.blacklist {
vec.push(name);
} else {
@ -887,10 +885,10 @@ impl<'help> Arg<'help> {
pub fn conflicts_with_all(mut self, names: &[&str]) -> Self {
if let Some(ref mut vec) = self.blacklist {
for s in names {
vec.push(s.key());
vec.push(s.into());
}
} else {
self.blacklist = Some(names.iter().map(Key::key).collect());
self.blacklist = Some(names.iter().map(Into::into).collect());
}
self
}
@ -1041,7 +1039,7 @@ impl<'help> Arg<'help> {
/// [`Multiple*`]: ./enum.ArgSettings.html#variant.MultipleValues
/// [`UseValueDelimiter`]: ./enum.ArgSettings.html#variant.UseValueDelimiter
pub fn overrides_with<T: Key>(mut self, arg_id: T) -> Self {
let name = arg_id.key();
let name = arg_id.into();
if let Some(ref mut vec) = self.overrides {
vec.push(name);
} else {
@ -1080,10 +1078,10 @@ impl<'help> Arg<'help> {
pub fn overrides_with_all<T: Key>(mut self, names: &[T]) -> Self {
if let Some(ref mut vec) = self.overrides {
for s in names {
vec.push(s.key());
vec.push(s.into());
}
} else {
self.overrides = Some(names.iter().map(Key::key).collect());
self.overrides = Some(names.iter().map(Into::into).collect());
}
self
}
@ -1144,7 +1142,7 @@ impl<'help> Arg<'help> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [override]: ./struct.Arg.html#method.overrides_with
pub fn requires<T: Key>(mut self, arg_id: T) -> Self {
let arg = arg_id.key();
let arg = arg_id.into();
if let Some(ref mut vec) = self.requires {
vec.push((None, arg));
} else {
@ -1213,7 +1211,7 @@ impl<'help> Arg<'help> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [override]: ./struct.Arg.html#method.overrides_with
pub fn requires_if<T: Key>(mut self, val: &'help str, arg_id: T) -> Self {
let arg = arg_id.key();
let arg = arg_id.into();
if let Some(ref mut vec) = self.requires {
vec.push((Some(val), arg));
} else {
@ -1276,12 +1274,12 @@ impl<'help> Arg<'help> {
pub fn requires_ifs<T: Key>(mut self, ifs: &[(&'help str, T)]) -> Self {
if let Some(ref mut vec) = self.requires {
for (val, arg) in ifs {
vec.push((Some(val), arg.key()));
vec.push((Some(val), arg.into()));
}
} else {
let mut vec = vec![];
for (val, arg) in ifs {
vec.push((Some(*val), arg.key()));
vec.push((Some(*val), arg.into()));
}
self.requires = Some(vec);
}
@ -1352,7 +1350,7 @@ impl<'help> Arg<'help> {
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
/// [required]: ./struct.Arg.html#method.required
pub fn required_if<T: Key>(mut self, arg_id: T, val: &'help str) -> Self {
let arg = arg_id.key();
let arg = arg_id.into();
if let Some(ref mut vec) = self.r_ifs {
vec.push((arg, val));
} else {
@ -1443,13 +1441,13 @@ impl<'help> Arg<'help> {
/// [required]: ./struct.Arg.html#method.required
pub fn required_ifs<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self {
if let Some(ref mut vec) = self.r_ifs {
for r_if in ifs {
vec.push((r_if.0.key(), r_if.1));
for (id, val) in ifs {
vec.push((Id::from_ref(id), *val));
}
} else {
let mut vec = vec![];
for r_if in ifs {
vec.push((r_if.0.key(), r_if.1));
for (id, val) in ifs {
vec.push((Id::from_ref(id), *val));
}
self.r_ifs = Some(vec);
}
@ -1521,10 +1519,10 @@ impl<'help> Arg<'help> {
pub fn requires_all<T: Key>(mut self, names: &[T]) -> Self {
if let Some(ref mut vec) = self.requires {
for s in names {
vec.push((None, s.key()));
vec.push((None, s.into()));
}
} else {
self.requires = Some(names.iter().map(|s| (None, s.key())).collect());
self.requires = Some(names.iter().map(|s| (None, s.into())).collect());
}
self
}
@ -1785,7 +1783,7 @@ impl<'help> Arg<'help> {
/// ```
/// [`ArgGroup`]: ./struct.ArgGroup.html
pub fn group<T: Key>(mut self, group_id: T) -> Self {
let name = group_id.key();
let name = group_id.into();
if let Some(ref mut vec) = self.groups {
vec.push(name);
} else {
@ -1828,10 +1826,10 @@ impl<'help> Arg<'help> {
pub fn groups<T: Key>(mut self, group_ids: &[T]) -> Self {
if let Some(ref mut vec) = self.groups {
for s in group_ids {
vec.push(s.key());
vec.push(s.into());
}
} else {
self.groups = Some(group_ids.iter().map(Key::key).collect());
self.groups = Some(group_ids.iter().map(Into::into).collect());
}
self
}
@ -2477,7 +2475,7 @@ impl<'help> Arg<'help> {
val: Option<&'help OsStr>,
default: &'help OsStr,
) -> Self {
let arg = arg_id.key();
let arg = arg_id.into();
self.setb(ArgSettings::TakesValue);
if let Some(ref mut vm) = self.default_vals_ifs {
let l = vm.len();
@ -4164,7 +4162,7 @@ impl<'a> Arg<'a> {
// Self conflict
if let Some(vec) = &self.blacklist {
assert!(
!vec.iter().any(|&x| x == self.id),
!vec.iter().any(|x| *x == self.id),
"Argument '{}' cannot conflict with itself",
self.name,
);

View file

@ -1,10 +1,9 @@
// Std
use std::fmt::{Debug, Formatter, Result};
// Internal
use crate::util::Key;
type Id = u64;
use crate::util::{Id, Key};
/// `ArgGroup`s are a family of related [arguments] and way for you to express, "Any of these
/// arguments". By placing arguments in a logical group, you can create easier requirement and
@ -96,7 +95,7 @@ impl<'a> ArgGroup<'a> {
}
/// @TODO @p2 @docs @v3-beta1: Write Docs
pub fn new<T: Key>(id: T) -> Self {
ArgGroup::_with_id(id.key())
ArgGroup::_with_id(id.into())
}
/// Creates a new instance of `ArgGroup` using a unique string name. The name will be used to
/// get values from the group or refer to the group inside of conflict and requirement rules.
@ -110,7 +109,7 @@ impl<'a> ArgGroup<'a> {
/// ```
pub fn with_name(n: &'a str) -> Self {
ArgGroup {
id: n.key(),
id: n.into(),
name: n,
..ArgGroup::default()
}
@ -152,7 +151,7 @@ impl<'a> ArgGroup<'a> {
/// ```
/// [argument]: ./struct.Arg.html
pub fn arg<T: Key>(mut self, arg_id: T) -> Self {
self.args.push(arg_id.key());
self.args.push(arg_id.into());
self
}
@ -298,7 +297,7 @@ impl<'a> ArgGroup<'a> {
/// [required group]: ./struct.ArgGroup.html#method.required
/// [argument requirement rules]: ./struct.Arg.html#method.requires
pub fn requires<T: Key>(mut self, id: T) -> Self {
let arg_id = id.key();
let arg_id = id.into();
if let Some(ref mut reqs) = self.requires {
reqs.push(arg_id);
} else {
@ -374,7 +373,7 @@ impl<'a> ArgGroup<'a> {
/// ```
/// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with
pub fn conflicts_with<T: Key>(mut self, id: T) -> Self {
let arg_id = id.key();
let arg_id = id.into();
if let Some(ref mut confs) = self.conflicts {
confs.push(arg_id);
} else {
@ -440,7 +439,7 @@ impl<'a> Debug for ArgGroup<'a> {
impl<'a, 'z> From<&'z ArgGroup<'a>> for ArgGroup<'a> {
fn from(g: &'z ArgGroup<'a>) -> Self {
ArgGroup {
id: g.id,
id: g.id.clone(),
name: g.name,
required: g.required,
args: g.args.clone(),
@ -503,8 +502,7 @@ impl<'a> From<&'a yaml_rust::yaml::Hash> for ArgGroup<'a> {
#[cfg(test)]
mod test {
use super::ArgGroup;
use super::Key;
use super::{ArgGroup, Id};
#[cfg(feature = "yaml")]
use yaml_rust::YamlLoader;
@ -522,9 +520,9 @@ mod test {
.requires_all(&["r2", "r3"])
.requires("r4");
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
assert_eq!(g.args, args);
assert_eq!(g.requires, Some(reqs));
@ -545,9 +543,24 @@ mod test {
.requires_all(&["r2", "r3"])
.requires("r4");
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
let args = vec![
Id::from("a1"),
Id::from("a4"),
Id::from("a2"),
Id::from("a3"),
];
let reqs = vec![
Id::from("r1"),
Id::from("r2"),
Id::from("r3"),
Id::from("r4"),
];
let confs = vec![
Id::from("c1"),
Id::from("c2"),
Id::from("c3"),
Id::from("c4"),
];
let debug_str = format!(
"{{\n\
@ -579,9 +592,9 @@ mod test {
.requires_all(&["r2", "r3"])
.requires("r4");
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
let g2 = ArgGroup::from(&g);
assert_eq!(g2.args, args);
@ -610,9 +623,9 @@ requires:
- r4";
let yml = &YamlLoader::load_from_str(g_yaml).expect("failed to load YAML file")[0];
let g = ArgGroup::from_yaml(yml);
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
assert_eq!(g.args, args);
assert_eq!(g.requires, Some(reqs));
assert_eq!(g.conflicts, Some(confs));
@ -622,7 +635,7 @@ requires:
impl<'a> Clone for ArgGroup<'a> {
fn clone(&self) -> Self {
ArgGroup {
id: self.id,
id: self.id.clone(),
name: self.name,
required: self.required,
args: self.args.clone(),

View file

@ -1,6 +1,6 @@
// Internal
use crate::build::{Arg, ArgSettings};
use crate::util::{Key, VecMap};
use crate::util::VecMap;
use crate::INTERNAL_ERROR_MSG;
#[derive(PartialEq, Debug)]
@ -90,7 +90,7 @@ impl<'a> UsageParser<'a> {
let name = &self.usage[self.start..self.pos];
if self.prev == UsageToken::Unknown {
debugln!("UsageParser::name: setting name...{}", name);
arg.id = name.key();
arg.id = name.into();
arg.name = name;
if arg.long.is_none() && arg.short.is_none() {
debugln!("UsageParser::name: explicit name set...");
@ -147,7 +147,7 @@ impl<'a> UsageParser<'a> {
let name = &self.usage[self.start..self.pos];
if !self.explicit_name_set {
debugln!("UsageParser::long: setting name...{}", name);
arg.id = name.key();
arg.id = name.into();
arg.name = name;
}
debugln!("UsageParser::long: setting long...{}", name);
@ -165,7 +165,7 @@ impl<'a> UsageParser<'a> {
// --long takes precedence but doesn't set self.explicit_name_set
let name = &start[..short.len_utf8()];
debugln!("UsageParser::short: setting name...{}", name);
arg.id = name.key();
arg.id = name.into();
arg.name = name;
}
self.prev = UsageToken::Short;

View file

@ -805,11 +805,11 @@ macro_rules! positionals {
macro_rules! groups_for_arg {
($app:expr, $grp:expr) => {{
debugln!("Parser::groups_for_arg: name={}", $grp);
debugln!("Parser::groups_for_arg: name={:?}", $grp);
$app.groups
.iter()
.filter(|grp| grp.args.iter().any(|&a| a == $grp))
.map(|grp| grp.id)
.filter(|grp| grp.args.iter().any(|a| *a == $grp))
.map(|grp| grp.id.clone())
}};
}

View file

@ -1,8 +1,7 @@
use crate::build::Arg;
use crate::util::Id;
use std::ffi::{OsStr, OsString};
type Id = u64;
#[derive(PartialEq, Debug, Clone)]
pub(crate) struct Key {
pub(crate) key: KeyType,
@ -112,14 +111,14 @@ impl<'b> MKeyMap<'b> {
//? probably shouldn't add a possibility for removal?
//? or remove by replacement by some dummy object, so the order is preserved
pub(crate) fn remove_by_name(&mut self, _name: Id) -> Option<Arg<'b>> {
pub(crate) fn remove_by_name(&mut self, name: &Id) -> Option<Arg<'b>> {
if self.built {
panic!("Cannot remove args after being built");
}
self.args
.iter()
.position(|arg| arg.id == _name)
.position(|arg| arg.id == *name)
.map(|i| self.args.swap_remove(i))
}
}

View file

@ -1,4 +1,5 @@
// std
use crate::util::Id;
use std::collections::{BTreeMap, VecDeque};
// Internal
@ -7,8 +8,6 @@ use crate::build::{Arg, ArgSettings};
use crate::parse::{ArgMatcher, Parser};
use crate::INTERNAL_ERROR_MSG;
type Id = u64;
pub(crate) struct Usage<'b, 'c, 'z>
where
'b: 'c,
@ -187,7 +186,7 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
{
debugln!("usage::get_args_tag:iter:{}:", pos.name);
for grp_s in groups_for_arg!(self.p.app, pos.id) {
debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.name, grp_s);
debugln!("usage::get_args_tag:iter:{:?}:iter:{:?};", pos.name, grp_s);
// if it's part of a required group we don't want to count it
if self
.p
@ -283,7 +282,7 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
}
}
for grp_s in groups_for_arg!(self.p.app, f.id) {
debugln!("usage::needs_flags_tag:iter:iter: grp_s={};", grp_s);
debugln!("usage::needs_flags_tag:iter:iter: grp_s={:?};", grp_s);
if self
.p
.app
@ -326,13 +325,13 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
let mut unrolled_reqs = vec![];
for &a in self.p.required.iter() {
for a in self.p.required.iter() {
if let Some(ref m) = matcher {
for aa in self.p.app.unroll_requirements_for_arg(a, m) {
unrolled_reqs.push(aa);
}
} else {
unrolled_reqs.push(a);
unrolled_reqs.push(a.clone());
}
}
@ -341,8 +340,8 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
.app
.groups
.iter()
.filter(|gn| self.p.required.contains(gn.id))
.flat_map(|g| self.p.app.unroll_args_in_group(g.id))
.filter(|gn| self.p.required.contains(&gn.id))
.flat_map(|g| self.p.app.unroll_args_in_group(&g.id))
.collect::<Vec<_>>();
let pmap = if let Some(m) = matcher {
@ -350,8 +349,8 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
.iter()
.chain(incls.iter())
.filter(|a| positionals!(self.p.app).any(|p| &&p.id == a))
.filter(|&&pos| !m.contains(pos))
.filter_map(|&pos| self.p.app.find(pos))
.filter(|&pos| !m.contains(pos))
.filter_map(|pos| self.p.app.find(pos))
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
.filter(|pos| !args_in_groups.contains(&pos.id))
.map(|pos| (pos.index.unwrap(), pos))
@ -361,38 +360,37 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
.iter()
.chain(incls.iter())
.filter(|a| positionals!(self.p.app).any(|p| &&p.id == a))
.filter_map(|&pos| self.p.app.find(pos))
.filter_map(|pos| self.p.app.find(pos))
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
.filter(|pos| !args_in_groups.contains(&pos.id))
.map(|pos| (pos.index.unwrap(), pos))
.collect::<BTreeMap<u64, &Arg>>() // sort by index
};
for &p in pmap.values() {
debugln!("Usage::get_required_usage_from:iter:{}", p.id);
let s = p.id;
if args_in_groups.is_empty() || !args_in_groups.contains(&s) {
for p in pmap.values() {
debugln!("Usage::get_required_usage_from:iter:{:?}", p.id);
if args_in_groups.is_empty() || !args_in_groups.contains(&p.id) {
ret_val.push_back(p.to_string());
}
}
for &a in unrolled_reqs
for a in unrolled_reqs
.iter()
.chain(incls.iter())
.filter(|name| !positionals!(self.p.app).any(|p| &&p.id == name))
.filter(|name| !self.p.app.groups.iter().any(|g| &&g.id == name))
.filter(|name| !args_in_groups.contains(name))
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(**name)))
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
{
debugln!("Usage::get_required_usage_from:iter:{}:", a);
debugln!("Usage::get_required_usage_from:iter:{:?}:", a);
let arg = self
.p
.app
.find(a)
.find(&a)
.map(ToString::to_string)
.expect(INTERNAL_ERROR_MSG);
ret_val.push_back(arg);
}
let mut g_vec: Vec<String> = vec![];
for &g in unrolled_reqs
for g in unrolled_reqs
.iter()
.filter(|n| self.p.app.groups.iter().any(|g| g.id == **n))
{

View file

@ -7,8 +7,7 @@ use std::ops::Deref;
// Internal
use crate::build::{Arg, ArgSettings};
use crate::parse::{ArgMatches, MatchedArg, SubCommand};
type Id = u64;
use crate::util::Id;
#[derive(Debug)]
pub(crate) struct ArgMatcher(pub(crate) ArgMatches);
@ -45,7 +44,7 @@ impl ArgMatcher {
global_arg_vec: &[Id],
vals_map: &mut HashMap<Id, MatchedArg>,
) {
for &global_arg in global_arg_vec {
for global_arg in global_arg_vec {
if let Some(ma) = self.get(global_arg) {
// We have to check if the parent's global arg wasn't used but still exists
// such as from a default value.
@ -53,7 +52,7 @@ impl ArgMatcher {
// For example, `myprog subcommand --global-arg=value` where --global-arg defines
// a default value of `other` myprog would have an existing MatchedArg for
// --global-arg where the value is `other`, however the occurs will be 0.
let to_update = if let Some(parent_ma) = vals_map.get(&global_arg) {
let to_update = if let Some(parent_ma) = vals_map.get(global_arg) {
if parent_ma.occurs > 0 && ma.occurs == 0 {
parent_ma.clone()
} else {
@ -62,7 +61,7 @@ impl ArgMatcher {
} else {
ma.clone()
};
vals_map.insert(global_arg, to_update);
vals_map.insert(global_arg.clone(), to_update);
}
}
if let Some(ref mut sc) = self.0.subcommand {
@ -71,21 +70,21 @@ impl ArgMatcher {
mem::swap(&mut am.0, &mut sc.matches);
}
for (&name, matched_arg) in vals_map.iter_mut() {
self.0.args.insert(name, matched_arg.clone());
for (name, matched_arg) in vals_map.iter_mut() {
self.0.args.insert(name.clone(), matched_arg.clone());
}
}
pub fn get_mut(&mut self, arg: Id) -> Option<&mut MatchedArg> {
self.0.args.get_mut(&arg)
pub fn get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg> {
self.0.args.get_mut(arg)
}
pub fn get(&self, arg: Id) -> Option<&MatchedArg> {
self.0.args.get(&arg)
pub fn get(&self, arg: &Id) -> Option<&MatchedArg> {
self.0.args.get(arg)
}
pub fn remove(&mut self, arg: Id) {
self.0.args.swap_remove(&arg);
pub fn remove(&mut self, arg: &Id) {
self.0.args.swap_remove(arg);
}
#[allow(dead_code)]
@ -95,12 +94,12 @@ impl ArgMatcher {
}
}
pub fn insert(&mut self, name: Id) {
self.0.args.insert(name, MatchedArg::new());
pub fn insert(&mut self, name: &Id) {
self.0.args.insert(name.clone(), MatchedArg::new());
}
pub fn contains(&self, arg: Id) -> bool {
self.0.args.contains_key(&arg)
pub fn contains(&self, arg: &Id) -> bool {
self.0.args.contains_key(arg)
}
pub fn is_empty(&self) -> bool {
@ -111,8 +110,8 @@ impl ArgMatcher {
self.0.args.keys()
}
pub fn entry(&mut self, arg: Id) -> indexmap::map::Entry<Id, MatchedArg> {
self.0.args.entry(arg)
pub fn entry(&mut self, arg: &Id) -> indexmap::map::Entry<Id, MatchedArg> {
self.0.args.entry(arg.clone())
}
pub fn subcommand(&mut self, sc: SubCommand) {
@ -127,8 +126,8 @@ impl ArgMatcher {
self.0.args.iter()
}
pub fn inc_occurrence_of(&mut self, arg: Id) {
debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg);
pub fn inc_occurrence_of(&mut self, arg: &Id) {
debugln!("ArgMatcher::inc_occurrence_of: arg={:?}", arg);
if let Some(a) = self.get_mut(arg) {
a.occurs += 1;
return;
@ -137,7 +136,7 @@ impl ArgMatcher {
self.insert(arg);
}
pub fn add_val_to(&mut self, arg: Id, val: &OsStr) {
pub fn add_val_to(&mut self, arg: &Id, val: &OsStr) {
let ma = self.entry(arg).or_insert(MatchedArg {
occurs: 0, // @TODO @question Shouldn't this be 1 if we're already adding a value to this arg?
indices: Vec::with_capacity(1),
@ -146,7 +145,7 @@ impl ArgMatcher {
ma.vals.push(val.to_owned());
}
pub fn add_index_to(&mut self, arg: Id, idx: usize) {
pub fn add_index_to(&mut self, arg: &Id, idx: usize) {
let ma = self.entry(arg).or_insert(MatchedArg {
occurs: 0,
indices: Vec::with_capacity(1),
@ -157,7 +156,7 @@ impl ArgMatcher {
pub fn needs_more_vals(&self, o: &Arg) -> bool {
debugln!("ArgMatcher::needs_more_vals: o={}", o.name);
if let Some(ma) = self.get(o.id) {
if let Some(ma) = self.get(&o.id) {
if let Some(num) = o.num_vals {
debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num);
return if o.is_set(ArgSettings::MultipleValues) {

View file

@ -11,11 +11,9 @@ use indexmap::IndexMap;
// Internal
use crate::parse::{MatchedArg, SubCommand};
use crate::util::Key;
use crate::util::{Id, Key};
use crate::{Error, INVALID_UTF8};
type Id = u64;
/// Used to get information about the arguments that were supplied to the program at runtime by
/// the user. New instances of this struct are obtained by using the [`App::get_matches`] family of
/// methods.
@ -107,7 +105,7 @@ impl ArgMatches {
/// [`ArgMatches::values_of`]: ./struct.ArgMatches.html#method.values_of
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
pub fn value_of<T: Key>(&self, id: T) -> Option<&str> {
if let Some(arg) = self.args.get(&id.key()) {
if let Some(arg) = self.args.get(&Id::from(id)) {
if let Some(v) = arg.vals.get(0) {
return Some(v.to_str().expect(INVALID_UTF8));
}
@ -139,7 +137,7 @@ impl ArgMatches {
/// ```
/// [`Arg::values_of_lossy`]: ./struct.ArgMatches.html#method.values_of_lossy
pub fn value_of_lossy<T: Key>(&self, id: T) -> Option<Cow<'_, str>> {
if let Some(arg) = self.args.get(&id.key()) {
if let Some(arg) = self.args.get(&Id::from(id)) {
if let Some(v) = arg.vals.get(0) {
return Some(v.to_string_lossy());
}
@ -176,7 +174,7 @@ impl ArgMatches {
/// [`ArgMatches::values_of_os`]: ./struct.ArgMatches.html#method.values_of_os
pub fn value_of_os<T: Key>(&self, id: T) -> Option<&OsStr> {
self.args
.get(&id.key())
.get(&Id::from(id))
.and_then(|arg| arg.vals.get(0).map(OsString::as_os_str))
}
@ -206,7 +204,7 @@ impl ArgMatches {
/// [`Values`]: ./struct.Values.html
/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
pub fn values_of<T: Key>(&self, id: T) -> Option<Values<'_>> {
self.args.get(&id.key()).map(|arg| {
self.args.get(&Id::from(id)).map(|arg| {
fn to_str_slice(o: &OsString) -> &str {
o.to_str().expect(INVALID_UTF8)
}
@ -243,7 +241,7 @@ impl ArgMatches {
/// assert_eq!(itr.next(), None);
/// ```
pub fn values_of_lossy<T: Key>(&self, id: T) -> Option<Vec<String>> {
self.args.get(&id.key()).map(|arg| {
self.args.get(&Id::from(id)).map(|arg| {
arg.vals
.iter()
.map(|v| v.to_string_lossy().into_owned())
@ -288,7 +286,7 @@ impl ArgMatches {
}
let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; // coerce to fn pointer
self.args.get(&id.key()).map(|arg| OsValues {
self.args.get(&Id::from(id)).map(|arg| OsValues {
iter: arg.vals.iter().map(to_str_slice),
})
}
@ -489,7 +487,7 @@ impl ArgMatches {
/// assert!(m.is_present("debug"));
/// ```
pub fn is_present<T: Key>(&self, id: T) -> bool {
let id = id.key();
let id = Id::from(id);
if let Some(ref sc) = self.subcommand {
if sc.id == id {
@ -539,7 +537,7 @@ impl ArgMatches {
/// assert_eq!(m.occurrences_of("flag"), 1);
/// ```
pub fn occurrences_of<T: Key>(&self, id: T) -> u64 {
self.args.get(&id.key()).map_or(0, |a| a.occurs)
self.args.get(&Id::from(id)).map_or(0, |a| a.occurs)
}
/// Gets the starting index of the argument in respect to all other arguments. Indices are
@ -673,7 +671,7 @@ impl ArgMatches {
/// [`ArgMatches`]: ./struct.ArgMatches.html
/// [delimiter]: ./struct.Arg.html#method.value_delimiter
pub fn index_of<T: Key>(&self, name: T) -> Option<usize> {
if let Some(arg) = self.args.get(&name.key()) {
if let Some(arg) = self.args.get(&Id::from(name)) {
if let Some(i) = arg.indices.get(0) {
return Some(*i);
}
@ -755,7 +753,7 @@ impl ArgMatches {
/// [`ArgMatches::index_of`]: ./struct.ArgMatches.html#method.index_of
/// [delimiter]: ./struct.Arg.html#method.value_delimiter
pub fn indices_of<T: Key>(&self, id: T) -> Option<Indices<'_>> {
self.args.get(&id.key()).map(|arg| Indices {
self.args.get(&Id::from(id)).map(|arg| Indices {
iter: arg.indices.iter().cloned(),
})
}
@ -793,7 +791,7 @@ impl ArgMatches {
/// [`ArgMatches`]: ./struct.ArgMatches.html
pub fn subcommand_matches<T: Key>(&self, id: T) -> Option<&ArgMatches> {
if let Some(ref s) = self.subcommand {
if s.id == id.key() {
if s.id == id.into() {
return Some(&s.matches);
}
}

View file

@ -1,8 +1,7 @@
// Internal
use crate::util::Id;
use crate::ArgMatches;
type Id = u64;
/// The abstract representation of a command line subcommand.
///
/// This struct describes all the valid options of the subcommand for the program. Subcommands are

View file

@ -20,13 +20,11 @@ use crate::parse::Validator;
use crate::parse::{ArgMatcher, SubCommand};
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
use crate::util::OsStrExt3;
use crate::util::{self, ChildGraph, Key, OsStrExt2, EMPTY_HASH};
use crate::util::{ChildGraph, Id, OsStrExt2};
use crate::INTERNAL_ERROR_MSG;
use crate::INVALID_UTF8;
type Id = u64;
#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum ParseResult {
Flag,
Opt(Id),
@ -114,7 +112,7 @@ where
.args
.iter()
.filter(|a| a.settings.is_set(ArgSettings::Required))
.map(|a| a.id)
.map(|a| a.id.clone())
{
reqs.insert(a);
}
@ -352,13 +350,13 @@ where
// Add args with default requirements
if a.is_set(ArgSettings::Required) {
debugln!("Parser::_build: adding {} to default requires", a.name);
let idx = self.required.insert(a.id);
let idx = self.required.insert(a.id.clone());
// If the arg is required, add all it's requirements to master required list
if let Some(ref areqs) = a.requires {
for name in areqs
.iter()
.filter(|&&(val, _)| val.is_none())
.map(|&(_, name)| name)
.filter(|(val, _)| val.is_none())
.map(|(_, name)| name.clone())
{
self.required.insert_child(idx, name);
}
@ -386,7 +384,7 @@ where
}) && positionals!(self.app).last().map_or(false, |p_name| {
!self
.app
.find(p_name.id)
.find(&p_name.id)
.expect(INTERNAL_ERROR_MSG)
.is_set(ArgSettings::Last)
}) {
@ -395,10 +393,10 @@ where
for group in &self.app.groups {
if group.required {
let idx = self.required.insert(group.id);
let idx = self.required.insert(group.id.clone());
if let Some(ref reqs) = group.requires {
for &a in reqs {
self.required.insert_child(idx, a);
for a in reqs {
self.required.insert_child(idx, a.clone());
}
}
}
@ -454,7 +452,7 @@ where
self.unset(AS::ValidNegNumFound);
// Is this a new argument, or values from a previous option?
let starts_new_arg = self.is_new_arg(arg_os, needs_val_of);
let starts_new_arg = self.is_new_arg(arg_os, needs_val_of.clone());
if !self.is_set(AS::TrailingValues)
&& arg_os.starts_with(b"--")
@ -536,7 +534,7 @@ where
}
} else if let ParseResult::Opt(name) = needs_val_of {
// Check to see if parsing a value from a previous arg
let arg = self.app.find(name).expect(INTERNAL_ERROR_MSG);
let arg = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
// get the option so we can check the settings
needs_val_of = self.add_val_to_arg(arg, arg_os, matcher)?;
// get the next value from the iterator
@ -599,7 +597,7 @@ where
if let Some(p) =
positionals!(self.app).find(|p| p.index == Some(pos_counter as u64))
{
ParseResult::Pos(p.id)
ParseResult::Pos(p.id.clone())
} else {
ParseResult::ValuesDone
}
@ -609,7 +607,7 @@ where
let sc_match = { self.possible_subcommand(n).is_some() };
if self.is_new_arg(n, needs_val_of)
if self.is_new_arg(n, needs_val_of.clone())
|| sc_match
|| !suggestions::did_you_mean(&n.to_string_lossy(), sc_names!(self.app))
.is_empty()
@ -675,12 +673,12 @@ where
self.app.settings.set(AS::TrailingValues);
}
self.seen.push(p.id);
self.seen.push(p.id.clone());
let _ = self.add_val_to_arg(p, arg_os, matcher)?;
matcher.inc_occurrence_of(p.id);
matcher.inc_occurrence_of(&p.id);
for grp in groups_for_arg!(self.app, p.id) {
matcher.inc_occurrence_of(grp);
matcher.inc_occurrence_of(&grp);
}
self.app.settings.set(AS::ValidArgFound);
@ -714,14 +712,12 @@ where
self.app.color(),
));
}
sc_m.add_val_to(EMPTY_HASH, &v);
sc_m.add_val_to(&Id::empty_hash(), &v);
}
let id = sc_name.key();
matcher.subcommand(SubCommand {
name: sc_name,
id,
name: sc_name.clone(),
id: sc_name.into(),
matches: sc_m.into_inner(),
});
@ -852,7 +848,7 @@ where
help_help = true;
break; // Maybe?
}
if let Some(id) = find_subcmd!(sc, cmd).map(|x| x.id) {
if let Some(id) = find_subcmd!(sc, cmd).map(|x| x.id.clone()) {
sc._propagate(Propagation::To(id));
}
@ -927,11 +923,11 @@ where
let arg_allows_tac = match needs_val_of {
ParseResult::Opt(name) => {
let o = self.app.find(name).expect(INTERNAL_ERROR_MSG);
let o = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
o.is_set(ArgSettings::AllowHyphenValues) || app_wide_settings
}
ParseResult::Pos(name) => {
let p = self.app.find(name).expect(INTERNAL_ERROR_MSG);
let p = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
p.is_set(ArgSettings::AllowHyphenValues) || app_wide_settings
}
ParseResult::ValuesDone => return true,
@ -988,7 +984,7 @@ where
mid_string.push_str(" ");
if let Some(id) = find_subcmd!(self.app, sc_name).map(|x| x.id) {
if let Some(id) = find_subcmd!(self.app, sc_name).map(|x| x.id.clone()) {
self.app._propagate(Propagation::To(id));
}
@ -1022,11 +1018,10 @@ where
let mut p = Parser::new(sc);
p.get_matches_with(&mut sc_matcher, it)?;
}
let name = sc.name.clone();
let sc_id = name.key();
let name = &sc.name;
matcher.subcommand(SubCommand {
id: sc_id, // @TODO @maybe: should be sc.id?
name,
id: Id::from_ref(&*name), // @TODO @maybe: should be sc.id?
name: name.to_string(),
matches: sc_matcher.into_inner(),
});
}
@ -1065,7 +1060,7 @@ where
);
// Needs to use app.settings.is_set instead of just is_set() because is_set() checks
// both global and local settings, we only want to check local
if let Some(help) = self.app.find(util::HELP_HASH) {
if let Some(help) = self.app.find(&Id::help_hash()) {
if let Some(h) = help.short {
if arg == h && !self.app.settings.is_set(AS::NoAutoHelp) {
sdebugln!("Help");
@ -1073,7 +1068,7 @@ where
}
}
}
if let Some(version) = self.app.find(util::VERSION_HASH) {
if let Some(version) = self.app.find(&Id::version_hash()) {
if let Some(v) = version.short {
if arg == v && !self.app.settings.is_set(AS::NoAutoVersion) {
sdebugln!("Version");
@ -1131,7 +1126,7 @@ where
);
self.app.settings.set(AS::ValidArgFound);
self.seen.push(opt.id);
self.seen.push(opt.id.clone());
if opt.is_set(ArgSettings::TakesValue) {
return Ok(self.parse_opt(val, opt, val.is_some(), matcher)?);
@ -1194,7 +1189,7 @@ where
c
);
self.app.settings.set(AS::ValidArgFound);
self.seen.push(opt.id);
self.seen.push(opt.id.clone());
if !opt.is_set(ArgSettings::TakesValue) {
self.check_for_help_and_version_char(c)?;
ret = self.parse_flag(opt, matcher)?;
@ -1284,10 +1279,10 @@ where
sdebugln!("None");
}
matcher.inc_occurrence_of(opt.id);
matcher.inc_occurrence_of(&opt.id);
// Increment or create the group "args"
for grp in groups_for_arg!(self.app, opt.id) {
matcher.inc_occurrence_of(grp);
matcher.inc_occurrence_of(&grp);
}
let needs_delim = opt.is_set(ArgSettings::RequireDelimiter);
@ -1298,7 +1293,7 @@ where
return Ok(ParseResult::ValuesDone);
} else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) {
debugln!("Parser::parse_opt: More arg vals required...");
return Ok(ParseResult::Opt(opt.id));
return Ok(ParseResult::Opt(opt.id.clone()));
}
debugln!("Parser::parse_opt: More arg vals not required...");
Ok(ParseResult::ValuesDone)
@ -1360,16 +1355,16 @@ where
}
}
matcher.add_val_to(arg.id, v);
matcher.add_index_to(arg.id, self.cur_idx.get());
matcher.add_val_to(&arg.id, v);
matcher.add_index_to(&arg.id, self.cur_idx.get());
// Increment or create the group "args"
for grp in groups_for_arg!(self.app, arg.id) {
matcher.add_val_to(grp, v);
matcher.add_val_to(&grp, v);
}
if matcher.needs_more_vals(arg) {
return Ok(ParseResult::Opt(arg.id));
return Ok(ParseResult::Opt(arg.id.clone()));
}
Ok(ParseResult::ValuesDone)
}
@ -1377,11 +1372,11 @@ where
fn parse_flag(&self, flag: &Arg<'b>, matcher: &mut ArgMatcher) -> ClapResult<ParseResult> {
debugln!("Parser::parse_flag;");
matcher.inc_occurrence_of(flag.id);
matcher.add_index_to(flag.id, self.cur_idx.get());
matcher.inc_occurrence_of(&flag.id);
matcher.add_index_to(&flag.id, self.cur_idx.get());
// Increment or create the group "args"
for grp in groups_for_arg!(self.app, flag.id) {
matcher.inc_occurrence_of(grp);
matcher.inc_occurrence_of(&grp);
}
Ok(ParseResult::Flag)
@ -1392,10 +1387,10 @@ where
let mut to_rem: Vec<Id> = Vec::new();
let mut self_override: Vec<Id> = Vec::new();
let mut arg_overrides = Vec::new();
for &name in matcher.arg_names() {
debugln!("Parser::remove_overrides:iter:{};", name);
for name in matcher.arg_names() {
debugln!("Parser::remove_overrides:iter:{:?};", name);
if let Some(arg) = self.app.find(name) {
let mut handle_self_override = |o| {
let mut handle_self_override = |o: &Id| {
if (arg.is_set(ArgSettings::MultipleValues)
|| arg.is_set(ArgSettings::MultipleOccurrences))
|| !arg.has_switch()
@ -1403,44 +1398,44 @@ where
return true;
}
debugln!(
"Parser::remove_overrides:iter:{}:iter:{}: self override;",
"Parser::remove_overrides:iter:{:?}:iter:{:?}: self override;",
name,
o
);
self_override.push(o);
self_override.push(o.clone());
false
};
if let Some(ref overrides) = arg.overrides {
debugln!("Parser::remove_overrides:iter:{}:{:?};", name, overrides);
for &o in overrides {
if o == arg.id {
debugln!("Parser::remove_overrides:iter:{:?}:{:?};", name, overrides);
for o in overrides {
if *o == arg.id {
if handle_self_override(o) {
continue;
}
} else {
arg_overrides.push((arg.id, o));
arg_overrides.push((o, arg.id));
arg_overrides.push((arg.id.clone(), o));
arg_overrides.push((o.clone(), &arg.id));
}
}
}
if self.is_set(AS::AllArgsOverrideSelf) {
let _ = handle_self_override(arg.id);
let _ = handle_self_override(&arg.id);
}
}
}
// remove future overrides in reverse seen order
for &arg in self.seen.iter().rev() {
for &(a, overr) in arg_overrides.iter().filter(|&&(a, _)| a == arg) {
for arg in self.seen.iter().rev() {
for (a, overr) in arg_overrides.iter().filter(|(a, _)| a == arg) {
if !to_rem.contains(&a) {
to_rem.push(overr);
to_rem.push((*overr).clone());
}
}
}
// Do self overrides
for &name in &self_override {
debugln!("Parser::remove_overrides:iter:self:{}: resetting;", name);
for name in &self_override {
debugln!("Parser::remove_overrides:iter:self:{:?}: resetting;", name);
if let Some(ma) = matcher.get_mut(name) {
if ma.occurs < 2 {
continue;
@ -1455,22 +1450,24 @@ where
}
// Finally remove conflicts
for &name in &to_rem {
debugln!("Parser::remove_overrides:iter:{}: removing;", name);
for name in &to_rem {
debugln!("Parser::remove_overrides:iter:{:?}: removing;", name);
matcher.remove(name);
self.overriden.push(name);
self.overriden.push(name.clone());
}
}
#[allow(clippy::cognitive_complexity)]
pub(crate) fn add_defaults(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
debugln!("Parser::add_defaults;");
// FIXME: Refactor into function (or at least most of it)
macro_rules! add_val {
(@default $_self:ident, $a:ident, $m:ident) => {
if let Some(ref vals) = $a.default_vals {
debugln!("Parser::add_defaults:iter:{}: has default vals", $a.name);
if $m
.get($a.id)
.get(&$a.id)
.map(|ma| ma.vals.len())
.map(|len| len == 0)
.unwrap_or(false)
@ -1482,7 +1479,7 @@ where
for val in vals {
$_self.add_val_to_arg($a, val, $m)?;
}
} else if $m.get($a.id).is_some() {
} else if $m.get(&$a.id).is_some() {
debugln!(
"Parser::add_defaults:iter:{}: has user defined vals",
$a.name
@ -1505,9 +1502,9 @@ where
if let Some(ref vm) = $a.default_vals_ifs {
sdebugln!(" has conditional defaults");
let mut done = false;
if $m.get($a.id).is_none() {
for &(arg, val, default) in vm.values() {
let add = if let Some(a) = $m.get(arg) {
if $m.get(&$a.id).is_none() {
for (arg, val, default) in vm.values() {
let add = if let Some(a) = $m.get(&arg) {
if let Some(v) = val {
a.vals.iter().any(|value| v == value)
} else {
@ -1588,17 +1585,17 @@ where
if let Some(ref name) = suffix.1 {
if let Some(opt) = self.app.args.get(&KeyType::Long(OsString::from(name))) {
for g in groups_for_arg!(self.app, opt.id) {
matcher.inc_occurrence_of(g);
matcher.inc_occurrence_of(&g);
}
matcher.insert(opt.id);
matcher.insert(&opt.id);
}
}
let used: Vec<Id> = matcher
.arg_names()
.filter(|n| {
if let Some(a) = self.app.find(**n) {
!(self.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
if let Some(a) = self.app.find(n) {
!(self.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
} else {
true
}

View file

@ -6,12 +6,10 @@ use crate::output::Usage;
use crate::parse::errors::Result as ClapResult;
use crate::parse::errors::{Error, ErrorKind};
use crate::parse::{ArgMatcher, MatchedArg, ParseResult, Parser};
use crate::util::ChildGraph;
use crate::util::{ChildGraph, Id};
use crate::INTERNAL_ERROR_MSG;
use crate::INVALID_UTF8;
type Id = u64;
pub struct Validator<'b, 'c, 'z>
where
'b: 'c,
@ -43,7 +41,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
debugln!("Validator::validate: needs_val_of={:?}", a);
self.validate_required(matcher)?;
let o = self.p.app.find(a).expect(INTERNAL_ERROR_MSG);
let o = self.p.app.find(&a).expect(INTERNAL_ERROR_MSG);
reqs_validated = true;
let should_err = if let Some(v) = matcher.0.args.get(&o.id) {
v.vals.is_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
@ -111,9 +109,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
if !ok {
let used: Vec<Id> = matcher
.arg_names()
.filter(|&&n| {
.filter(|&n| {
if let Some(a) = self.p.app.find(n) {
!(self.p.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
!(self.p.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
} else {
true
}
@ -131,7 +129,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
}
if !arg.is_set(ArgSettings::AllowEmptyValues)
&& val.is_empty()
&& matcher.contains(arg.id)
&& matcher.contains(&arg.id)
{
debugln!("Validator::validate_arg_values: illegal empty val found");
return Err(Error::empty_value(
@ -166,11 +164,11 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
Ok(())
}
fn build_conflict_err(&self, name: Id, matcher: &ArgMatcher) -> ClapResult<()> {
debugln!("build_err!: name={}", name);
fn build_conflict_err(&self, name: &Id, matcher: &ArgMatcher) -> ClapResult<()> {
debugln!("build_err!: name={:?}", name);
let usg = Usage::new(self.p).create_usage_with_title(&[]);
if let Some(other_arg) = self.p.app.find(name) {
for &k in matcher.arg_names() {
for k in matcher.arg_names() {
if let Some(a) = self.p.app.find(k) {
if let Some(ref v) = a.blacklist {
if v.contains(&name) {
@ -184,8 +182,8 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
}
}
}
} else if let Some(g) = self.p.app.groups.iter().find(|x| x.id == name) {
let args_in_group = self.p.app.unroll_args_in_group(g.id);
} else if let Some(g) = self.p.app.groups.iter().find(|x| x.id == *name) {
let args_in_group = self.p.app.unroll_args_in_group(&g.id);
let first = matcher
.arg_names()
.find(|x| args_in_group.contains(x))
@ -193,10 +191,10 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
let c_with = matcher
.arg_names()
.find(|x| x != &first && args_in_group.contains(x))
.map(|&x| self.p.app.find(x).expect(INTERNAL_ERROR_MSG).to_string());
.map(|x| self.p.app.find(x).expect(INTERNAL_ERROR_MSG).to_string());
debugln!("build_err!:c_with={:?}:group", c_with);
return Err(Error::argument_conflict(
self.p.app.find(*first).expect(INTERNAL_ERROR_MSG),
self.p.app.find(first).expect(INTERNAL_ERROR_MSG),
c_with,
&*usg,
self.p.app.color(),
@ -214,7 +212,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
}
self.gather_conflicts(matcher);
for name in self.c.iter() {
debugln!("Validator::validate_conflicts:iter:{};", name);
debugln!("Validator::validate_conflicts:iter:{:?};", name);
let mut should_err = false;
if let Some(g) = self
.p
@ -227,34 +225,34 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
let conf_with_self = self
.p
.app
.unroll_args_in_group(g.id)
.unroll_args_in_group(&g.id)
.iter()
.filter(|&&a| matcher.contains(a))
.filter(|&a| matcher.contains(a))
.count()
> 1;
let conf_with_arg = if let Some(ref c) = g.conflicts {
c.iter().any(|&x| matcher.contains(x))
c.iter().any(|x| matcher.contains(x))
} else {
false
};
let arg_conf_with_gr = matcher
.arg_names()
.filter_map(|&x| self.p.app.find(x))
.filter_map(|x| self.p.app.find(x))
.filter_map(|x| x.blacklist.as_ref())
.any(|c| c.iter().any(|&c| c == g.id));
.any(|c| c.iter().any(|c| *c == g.id));
should_err = conf_with_self || conf_with_arg || arg_conf_with_gr;
} else if let Some(ma) = matcher.get(*name) {
} else if let Some(ma) = matcher.get(name) {
debugln!(
"Validator::validate_conflicts:iter:{}: matcher contains it...",
"Validator::validate_conflicts:iter:{:?}: matcher contains it...",
name
);
should_err = ma.occurs > 0;
}
if should_err {
return self.build_conflict_err(*name, matcher);
return self.build_conflict_err(name, matcher);
}
}
Ok(())
@ -263,9 +261,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
fn validate_exclusive(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
debugln!("Validator::validate_exclusive;");
let args_count = matcher.arg_names().count();
for &name in matcher.arg_names() {
for name in matcher.arg_names() {
debugln!(
"Validator::validate_conflicts_with_everything:iter:{};",
"Validator::validate_conflicts_with_everything:iter:{:?};",
name
);
if let Some(arg) = self.p.app.find(name) {
@ -292,29 +290,32 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
// and such
fn gather_conflicts(&mut self, matcher: &mut ArgMatcher) {
debugln!("Validator::gather_conflicts;");
for &name in matcher.arg_names() {
debugln!("Validator::gather_conflicts:iter:{};", name);
for name in matcher.arg_names() {
debugln!("Validator::gather_conflicts:iter:{:?};", name);
if let Some(arg) = self.p.app.find(name) {
// Since an arg was used, every arg it conflicts with is added to the conflicts
if let Some(ref bl) = arg.blacklist {
for &conf in bl {
for conf in bl {
if self.p.app.find(conf).is_some() {
if conf != name {
self.c.insert(conf);
self.c.insert(conf.clone());
}
} else {
// for g_arg in self.p.app.unroll_args_in_group(conf) {
// if &g_arg != name {
self.c.insert(conf); // TODO ERROR is here - groups allow one arg but this line disallows all group args
// }
// }
self.c.insert(conf.clone()); // TODO ERROR is here - groups allow one arg but this line disallows all group args
// }
// }
}
}
}
// Now we need to know which groups this arg was a memeber of, to add all other
// args in that group to the conflicts, as well as any args those args conflict
// with
for grp in groups_for_arg!(self.p.app, name) {
// // FIXME: probably no need to cone the id here. Review the macro
for grp in groups_for_arg!(self.p.app, name.clone()) {
if let Some(g) = self
.p
.app
@ -325,7 +326,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
{
// for g_arg in self.p.app.unroll_args_in_group(&g.name) {
// if &g_arg != name {
self.c.insert(g.id);
self.c.insert(g.id.clone());
// }
// }
}
@ -336,27 +337,27 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
.groups
.iter()
.filter(|g| !g.multiple)
.find(|grp| grp.id == name)
.find(|grp| grp.id == *name)
{
debugln!("Validator::gather_conflicts:iter:{}:group;", name);
self.c.insert(g.id);
debugln!("Validator::gather_conflicts:iter:{:?}:group;", name);
self.c.insert(g.id.clone());
}
}
}
fn gather_requirements(&mut self, matcher: &ArgMatcher) {
debugln!("Validator::gather_requirements;");
for &name in matcher.arg_names() {
debugln!("Validator::gather_requirements:iter:{};", name);
for name in matcher.arg_names() {
debugln!("Validator::gather_requirements:iter:{:?};", name);
if let Some(arg) = self.p.app.find(name) {
for req in self.p.app.unroll_requirements_for_arg(arg.id, matcher) {
for req in self.p.app.unroll_requirements_for_arg(&arg.id, matcher) {
self.p.required.insert(req);
}
} else if let Some(g) = self.p.app.groups.iter().find(|grp| grp.id == name) {
debugln!("Validator::gather_conflicts:iter:{}:group;", name);
} else if let Some(g) = self.p.app.groups.iter().find(|grp| grp.id == *name) {
debugln!("Validator::gather_conflicts:iter:{:?}:group;", name);
if let Some(ref reqs) = g.requires {
for &r in reqs {
self.p.required.insert(r);
for r in reqs {
self.p.required.insert(r.clone());
}
}
}
@ -365,9 +366,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
fn validate_matched_args(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
debugln!("Validator::validate_matched_args;");
for (&name, ma) in matcher.iter() {
for (name, ma) in matcher.iter() {
debugln!(
"Validator::validate_matched_args:iter:{}: vals={:#?}",
"Validator::validate_matched_args:iter:{:?}: vals={:#?}",
name,
ma.vals
);
@ -382,10 +383,10 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
.app
.groups
.iter()
.find(|g| g.id == name)
.find(|g| g.id == *name)
.expect(INTERNAL_ERROR_MSG);
if let Some(ref g_reqs) = grp.requires {
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
if g_reqs.iter().any(|n| !matcher.contains(n)) {
return self.missing_required_error(matcher, Some(name));
}
}
@ -396,7 +397,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
debugln!(
"Validator::validate_arg_num_occurs: {}={};",
"Validator::validate_arg_num_occurs: {:?}={};",
a.name,
ma.occurs
);
@ -486,18 +487,18 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
ma: &MatchedArg,
matcher: &ArgMatcher,
) -> ClapResult<()> {
debugln!("Validator::validate_arg_requires:{};", a.name);
debugln!("Validator::validate_arg_requires:{:?};", a.name);
if let Some(ref a_reqs) = a.requires {
for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
for (val, name) in a_reqs.iter().filter(|(val, _)| val.is_some()) {
let missing_req =
|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name);
|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(&name);
if ma.vals.iter().any(missing_req) {
return self.missing_required_error(matcher, Some(a.id));
return self.missing_required_error(matcher, Some(&a.id));
}
}
for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) {
if !matcher.contains(name) {
return self.missing_required_error(matcher, Some(name));
for (_, name) in a_reqs.iter().filter(|(val, _)| val.is_none()) {
if !matcher.contains(&name) {
return self.missing_required_error(matcher, Some(&name));
}
}
}
@ -511,19 +512,19 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
);
self.gather_requirements(matcher);
for &arg_or_group in self.p.required.iter().filter(|&&r| !matcher.contains(r)) {
for arg_or_group in self.p.required.iter().filter(|r| !matcher.contains(r)) {
debugln!("Validator::validate_required:iter:aog={:?};", arg_or_group);
if let Some(arg) = self.p.app.find(arg_or_group) {
if let Some(arg) = self.p.app.find(&arg_or_group) {
if !self.is_missing_required_ok(arg, matcher) {
return self.missing_required_error(matcher, None);
}
} else if let Some(group) = self.p.app.groups.iter().find(|g| g.id == arg_or_group) {
} else if let Some(group) = self.p.app.groups.iter().find(|g| g.id == *arg_or_group) {
if !self
.p
.app
.unroll_args_in_group(group.id)
.unroll_args_in_group(&group.id)
.iter()
.any(|&a| matcher.contains(a))
.any(|a| matcher.contains(a))
{
return self.missing_required_error(matcher, None);
}
@ -541,9 +542,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
.map(|a| (a, a.r_ifs.as_ref().unwrap()))
{
for (other, val) in r_ifs.iter() {
if let Some(ma) = matcher.get(*other) {
if ma.contains_val(val) && !matcher.contains(a.id) {
return self.missing_required_error(matcher, Some(a.id));
if let Some(ma) = matcher.get(other) {
if ma.contains_val(val) && !matcher.contains(&a.id) {
return self.missing_required_error(matcher, Some(&a.id));
}
}
}
@ -561,15 +562,15 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
a.blacklist
.as_ref()
.map(|bl| {
bl.iter().any(|&conf| {
bl.iter().any(|conf| {
matcher.contains(conf)
|| self
.p
.app
.groups
.iter()
.find(|g| g.id == conf)
.map_or(false, |g| g.args.iter().any(|&arg| matcher.contains(arg)))
.find(|g| g.id == *conf)
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
})
})
.unwrap_or(false)
@ -584,11 +585,11 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
.args
.iter()
.filter(|a| a.r_unless.is_some())
.filter(|a| !matcher.contains(a.id))
.filter(|a| !matcher.contains(&a.id))
{
debugln!("Validator::validate_required_unless:iter:{};", a.name);
if self.fails_arg_required_unless(a, matcher) {
return self.missing_required_error(matcher, Some(a.id));
return self.missing_required_error(matcher, Some(&a.id));
}
}
@ -602,7 +603,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
($how:ident, $_self:expr, $a:ident, $m:ident) => {{
$a.r_unless
.as_ref()
.map(|ru| !ru.iter().$how(|&n| $m.contains(n)))
.map(|ru| !ru.iter().$how(|n| $m.contains(n)))
.unwrap_or(false)
}};
}
@ -616,7 +617,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
}
// `incl`: an arg to include in the error even if not used
fn missing_required_error(&self, matcher: &ArgMatcher, incl: Option<Id>) -> ClapResult<()> {
fn missing_required_error(&self, matcher: &ArgMatcher, incl: Option<&Id>) -> ClapResult<()> {
debugln!("Validator::missing_required_error; incl={:?}", incl);
let c = Colorizer::new(&ColorizerOption {
use_stderr: true,
@ -628,7 +629,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
);
let usg = Usage::new(self.p);
let req_args = if let Some(x) = incl {
usg.get_required_usage_from(&[x], Some(matcher), true)
usg.get_required_usage_from(&[x.clone()], Some(matcher), true)
.iter()
.fold(String::new(), |acc, s| {
acc + &format!("\n {}", c.error(s))[..]
@ -646,15 +647,15 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
);
let used: Vec<Id> = matcher
.arg_names()
.filter(|&&n| {
.filter(|&n| {
if let Some(a) = self.p.app.find(n) {
!(self.p.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
!(self.p.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
} else {
true
}
})
.cloned()
.chain(incl)
.chain(incl.cloned())
.collect();
Err(Error::missing_required_argument(
&*req_args,

View file

@ -1,3 +1,4 @@
use std::fmt::Display;
use std::hash::{Hash, Hasher};
// precompute some common values
@ -6,13 +7,13 @@ pub static VERSION_HASH: u64 = 0x30FF_0B7C_4D07_9478;
pub static EMPTY_HASH: u64 = 0x1C9D_3ADB_639F_298E;
const MAGIC_INIT: u64 = 0x811C_9DC5;
pub trait Key: Hash {
pub trait Key: Hash + Display {
fn key(&self) -> u64;
}
impl<T> Key for T
where
T: Hash,
T: Hash + Display,
{
fn key(&self) -> u64 {
let mut hasher = FnvHasher::new();

View file

@ -15,14 +15,14 @@ pub struct ChildGraph<T>(Vec<Child<T>>);
impl<T> ChildGraph<T>
where
T: Sized + PartialEq + Copy + Clone,
T: Sized + PartialEq + Clone,
{
pub fn with_capacity(s: usize) -> Self {
ChildGraph(Vec::with_capacity(s))
}
pub fn insert(&mut self, req: T) -> usize {
if !self.contains(req) {
if !self.contains(&req) {
let idx = self.0.len();
self.0.push(Child::new(req));
idx
@ -55,7 +55,7 @@ where
self.0.iter().map(|r| &r.id)
}
pub fn contains(&self, req: T) -> bool {
self.0.iter().any(|r| r.id == req)
pub fn contains(&self, req: &T) -> bool {
self.0.iter().any(|r| r.id == *req)
}
}

85
src/util/id.rs Normal file
View file

@ -0,0 +1,85 @@
use crate::util::fnv::{Key, EMPTY_HASH, HELP_HASH, VERSION_HASH};
use std::fmt::{Debug, Formatter, Result};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
#[derive(Clone, Eq, Default)]
#[cfg_attr(not(debug_assertions), derive(Copy), repr(transparent))]
pub(crate) struct Id {
#[cfg(debug_assertions)]
name: String,
id: u64,
}
macro_rules! precomputed_hashes {
($($fn_name:ident, $const_name:ident, $name:expr;)*) => {
impl Id {
$(
pub(crate) fn $fn_name() -> Self {
Id {
#[cfg(debug_assertions)]
name: $name.into(),
id: $const_name,
}
}
)*
}
};
}
precomputed_hashes! {
empty_hash, EMPTY_HASH, "";
help_hash, HELP_HASH, "help";
version_hash, VERSION_HASH, "version";
}
impl Id {
pub(crate) fn from_ref<T: Key>(val: T) -> Self {
Id {
#[cfg(debug_assertions)]
name: val.to_string(),
id: val.key(),
}
}
}
impl Debug for Id {
fn fmt(&self, f: &mut Formatter) -> Result {
#[cfg(debug_assertions)]
write!(f, "{:?} ", self.name)?;
write!(f, "[hash: {}]", self.id)
}
}
impl Deref for Id {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.id
}
}
impl<T: Key> From<T> for Id {
fn from(val: T) -> Self {
Id {
#[cfg(debug_assertions)]
name: val.to_string(),
id: val.key(),
}
}
}
impl Hash for Id {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.id.hash(state)
}
}
impl PartialEq for Id {
fn eq(&self, other: &Id) -> bool {
self.id == other.id
}
}

View file

@ -1,13 +1,13 @@
mod fnv;
mod graph;
mod id;
mod map;
mod osstringext;
mod strext;
pub use self::fnv::{Key, EMPTY_HASH, HELP_HASH, VERSION_HASH};
pub use self::graph::ChildGraph;
pub use self::map::{Values, VecMap};
pub(crate) use self::osstringext::OsStrExt2;
pub use self::{fnv::Key, map::Values};
pub(crate) use self::{graph::ChildGraph, id::Id, map::VecMap, osstringext::OsStrExt2};
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
pub(crate) use self::osstringext::OsStrExt3;
pub use self::strext::_StrExt;