diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index c2a00f9e..76d2aabc 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -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>(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 { + pub(crate) fn unroll_args_in_group(&self, group: &Id) -> Vec { 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 { - let requires_if_or_not = |&(val, req_arg)| { + pub(crate) fn unroll_requirements_for_arg(&self, arg: &Id, matcher: &ArgMatcher) -> Vec { + let requires_if_or_not = |(val, req_arg): &(Option<&str>, Id)| -> Option { 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); diff --git a/src/build/arg/mod.rs b/src/build/arg/mod.rs index eb03a498..0c6c70ca 100644 --- a/src/build/arg/mod.rs +++ b/src/build/arg/mod.rs @@ -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 Result<(), String>>; type ValidatorOs = Rc 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: T) -> Self { + pub fn new(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(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(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(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(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(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(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(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(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(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(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(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(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, ); diff --git a/src/build/arg_group.rs b/src/build/arg_group.rs index b3a89bb7..69681308 100644 --- a/src/build/arg_group.rs +++ b/src/build/arg_group.rs @@ -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(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(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(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(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(), diff --git a/src/build/usage_parser.rs b/src/build/usage_parser.rs index 7992b3c8..984d7461 100644 --- a/src/build/usage_parser.rs +++ b/src/build/usage_parser.rs @@ -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; diff --git a/src/macros.rs b/src/macros.rs index db821370..3bb48e82 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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()) }}; } diff --git a/src/mkeymap.rs b/src/mkeymap.rs index 2f0aa39a..83aad410 100644 --- a/src/mkeymap.rs +++ b/src/mkeymap.rs @@ -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> { + pub(crate) fn remove_by_name(&mut self, name: &Id) -> Option> { 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)) } } diff --git a/src/output/usage.rs b/src/output/usage.rs index 82cc3e1f..15f9213d 100644 --- a/src/output/usage.rs +++ b/src/output/usage.rs @@ -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::>(); 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::>() // 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 = vec![]; - for &g in unrolled_reqs + for g in unrolled_reqs .iter() .filter(|n| self.p.app.groups.iter().any(|g| g.id == **n)) { diff --git a/src/parse/arg_matcher.rs b/src/parse/arg_matcher.rs index d83ee3e9..267d888b 100644 --- a/src/parse/arg_matcher.rs +++ b/src/parse/arg_matcher.rs @@ -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, ) { - 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 { - self.0.args.entry(arg) + pub fn entry(&mut self, arg: &Id) -> indexmap::map::Entry { + 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) { diff --git a/src/parse/matches/arg_matches.rs b/src/parse/matches/arg_matches.rs index c44c3870..bf59bb66 100644 --- a/src/parse/matches/arg_matches.rs +++ b/src/parse/matches/arg_matches.rs @@ -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(&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(&self, id: T) -> Option> { - 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(&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(&self, id: T) -> Option> { - 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(&self, id: T) -> Option> { - 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(&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(&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(&self, name: T) -> Option { - 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(&self, id: T) -> Option> { - 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(&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); } } diff --git a/src/parse/matches/subcommand.rs b/src/parse/matches/subcommand.rs index b799d6ea..dbeac921 100644 --- a/src/parse/matches/subcommand.rs +++ b/src/parse/matches/subcommand.rs @@ -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 diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 500178aa..93fdf1ee 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -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 { 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 = Vec::new(); let mut self_override: Vec = 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 = 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 } diff --git a/src/parse/validator.rs b/src/parse/validator.rs index cfadb873..6cd634ab 100644 --- a/src/parse/validator.rs +++ b/src/parse/validator.rs @@ -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 = 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) -> 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 = 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, diff --git a/src/util/fnv.rs b/src/util/fnv.rs index 0ace0f17..0fc2a8a5 100644 --- a/src/util/fnv.rs +++ b/src/util/fnv.rs @@ -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 Key for T where - T: Hash, + T: Hash + Display, { fn key(&self) -> u64 { let mut hasher = FnvHasher::new(); diff --git a/src/util/graph.rs b/src/util/graph.rs index 2cd5818f..3864532b 100644 --- a/src/util/graph.rs +++ b/src/util/graph.rs @@ -15,14 +15,14 @@ pub struct ChildGraph(Vec>); impl ChildGraph 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) } } diff --git a/src/util/id.rs b/src/util/id.rs new file mode 100644 index 00000000..cf1c1d24 --- /dev/null +++ b/src/util/id.rs @@ -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(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 From for Id { + fn from(val: T) -> Self { + Id { + #[cfg(debug_assertions)] + name: val.to_string(), + id: val.key(), + } + } +} + +impl Hash for Id { + fn hash(&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 + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 502ac6a0..e12eb0d4 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -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;