119625d8cSopenharmony_ciuse std::iter::Iterator; 219625d8cSopenharmony_ciuse std::ops::Index; 319625d8cSopenharmony_ci 419625d8cSopenharmony_ciuse crate::builder::OsStr; 519625d8cSopenharmony_ciuse crate::Arg; 619625d8cSopenharmony_ciuse crate::INTERNAL_ERROR_MSG; 719625d8cSopenharmony_ci 819625d8cSopenharmony_ci#[derive(PartialEq, Eq, Debug, Clone)] 919625d8cSopenharmony_cipub(crate) struct Key { 1019625d8cSopenharmony_ci key: KeyType, 1119625d8cSopenharmony_ci index: usize, 1219625d8cSopenharmony_ci} 1319625d8cSopenharmony_ci 1419625d8cSopenharmony_ci#[derive(Default, PartialEq, Eq, Debug, Clone)] 1519625d8cSopenharmony_cipub(crate) struct MKeyMap { 1619625d8cSopenharmony_ci /// All of the arguments. 1719625d8cSopenharmony_ci args: Vec<Arg>, 1819625d8cSopenharmony_ci 1919625d8cSopenharmony_ci // Cache part: 2019625d8cSopenharmony_ci /// Will be set after `_build()`. 2119625d8cSopenharmony_ci keys: Vec<Key>, 2219625d8cSopenharmony_ci} 2319625d8cSopenharmony_ci 2419625d8cSopenharmony_ci#[derive(Debug, PartialEq, Eq, Hash, Clone)] 2519625d8cSopenharmony_cipub(crate) enum KeyType { 2619625d8cSopenharmony_ci Short(char), 2719625d8cSopenharmony_ci Long(OsStr), 2819625d8cSopenharmony_ci Position(usize), 2919625d8cSopenharmony_ci} 3019625d8cSopenharmony_ci 3119625d8cSopenharmony_ciimpl KeyType { 3219625d8cSopenharmony_ci pub(crate) fn is_position(&self) -> bool { 3319625d8cSopenharmony_ci matches!(self, KeyType::Position(_)) 3419625d8cSopenharmony_ci } 3519625d8cSopenharmony_ci} 3619625d8cSopenharmony_ci 3719625d8cSopenharmony_ciimpl PartialEq<usize> for KeyType { 3819625d8cSopenharmony_ci fn eq(&self, rhs: &usize) -> bool { 3919625d8cSopenharmony_ci match self { 4019625d8cSopenharmony_ci KeyType::Position(x) => x == rhs, 4119625d8cSopenharmony_ci _ => false, 4219625d8cSopenharmony_ci } 4319625d8cSopenharmony_ci } 4419625d8cSopenharmony_ci} 4519625d8cSopenharmony_ci 4619625d8cSopenharmony_ciimpl PartialEq<&str> for KeyType { 4719625d8cSopenharmony_ci fn eq(&self, rhs: &&str) -> bool { 4819625d8cSopenharmony_ci match self { 4919625d8cSopenharmony_ci KeyType::Long(l) => l == rhs, 5019625d8cSopenharmony_ci _ => false, 5119625d8cSopenharmony_ci } 5219625d8cSopenharmony_ci } 5319625d8cSopenharmony_ci} 5419625d8cSopenharmony_ci 5519625d8cSopenharmony_ciimpl PartialEq<str> for KeyType { 5619625d8cSopenharmony_ci fn eq(&self, rhs: &str) -> bool { 5719625d8cSopenharmony_ci match self { 5819625d8cSopenharmony_ci KeyType::Long(l) => l == rhs, 5919625d8cSopenharmony_ci _ => false, 6019625d8cSopenharmony_ci } 6119625d8cSopenharmony_ci } 6219625d8cSopenharmony_ci} 6319625d8cSopenharmony_ci 6419625d8cSopenharmony_ciimpl PartialEq<OsStr> for KeyType { 6519625d8cSopenharmony_ci fn eq(&self, rhs: &OsStr) -> bool { 6619625d8cSopenharmony_ci match self { 6719625d8cSopenharmony_ci KeyType::Long(l) => l == rhs, 6819625d8cSopenharmony_ci _ => false, 6919625d8cSopenharmony_ci } 7019625d8cSopenharmony_ci } 7119625d8cSopenharmony_ci} 7219625d8cSopenharmony_ci 7319625d8cSopenharmony_ciimpl PartialEq<char> for KeyType { 7419625d8cSopenharmony_ci fn eq(&self, rhs: &char) -> bool { 7519625d8cSopenharmony_ci match self { 7619625d8cSopenharmony_ci KeyType::Short(c) => c == rhs, 7719625d8cSopenharmony_ci _ => false, 7819625d8cSopenharmony_ci } 7919625d8cSopenharmony_ci } 8019625d8cSopenharmony_ci} 8119625d8cSopenharmony_ci 8219625d8cSopenharmony_ciimpl MKeyMap { 8319625d8cSopenharmony_ci /// If any arg has corresponding key in this map, we can search the key with 8419625d8cSopenharmony_ci /// u64(for positional argument), char(for short flag), &str and OsString 8519625d8cSopenharmony_ci /// (for long flag) 8619625d8cSopenharmony_ci pub(crate) fn contains<K>(&self, key: K) -> bool 8719625d8cSopenharmony_ci where 8819625d8cSopenharmony_ci KeyType: PartialEq<K>, 8919625d8cSopenharmony_ci { 9019625d8cSopenharmony_ci self.keys.iter().any(|x| x.key == key) 9119625d8cSopenharmony_ci } 9219625d8cSopenharmony_ci 9319625d8cSopenharmony_ci /// Push an argument in the map. 9419625d8cSopenharmony_ci pub(crate) fn push(&mut self, new_arg: Arg) { 9519625d8cSopenharmony_ci self.args.push(new_arg); 9619625d8cSopenharmony_ci } 9719625d8cSopenharmony_ci 9819625d8cSopenharmony_ci /// Find the arg have corresponding key in this map, we can search the key 9919625d8cSopenharmony_ci /// with u64(for positional argument), char(for short flag), &str and 10019625d8cSopenharmony_ci /// OsString (for long flag) 10119625d8cSopenharmony_ci pub(crate) fn get<K: ?Sized>(&self, key: &K) -> Option<&Arg> 10219625d8cSopenharmony_ci where 10319625d8cSopenharmony_ci KeyType: PartialEq<K>, 10419625d8cSopenharmony_ci { 10519625d8cSopenharmony_ci self.keys 10619625d8cSopenharmony_ci .iter() 10719625d8cSopenharmony_ci .find(|k| &k.key == key) 10819625d8cSopenharmony_ci .map(|k| &self.args[k.index]) 10919625d8cSopenharmony_ci } 11019625d8cSopenharmony_ci 11119625d8cSopenharmony_ci /// Return iterators of all keys. 11219625d8cSopenharmony_ci pub(crate) fn keys(&self) -> impl Iterator<Item = &KeyType> { 11319625d8cSopenharmony_ci self.keys.iter().map(|x| &x.key) 11419625d8cSopenharmony_ci } 11519625d8cSopenharmony_ci 11619625d8cSopenharmony_ci /// Return iterators of all args. 11719625d8cSopenharmony_ci pub(crate) fn args(&self) -> impl Iterator<Item = &Arg> { 11819625d8cSopenharmony_ci self.args.iter() 11919625d8cSopenharmony_ci } 12019625d8cSopenharmony_ci 12119625d8cSopenharmony_ci /// Return mutable iterators of all args. 12219625d8cSopenharmony_ci pub(crate) fn args_mut(&mut self) -> impl Iterator<Item = &mut Arg> { 12319625d8cSopenharmony_ci self.args.iter_mut() 12419625d8cSopenharmony_ci } 12519625d8cSopenharmony_ci 12619625d8cSopenharmony_ci /// We need a lazy build here since some we may change args after creating 12719625d8cSopenharmony_ci /// the map, you can checkout who uses `args_mut`. 12819625d8cSopenharmony_ci pub(crate) fn _build(&mut self) { 12919625d8cSopenharmony_ci // There will be at least as many keys as args, so that is a good starting point 13019625d8cSopenharmony_ci self.keys.reserve(self.args.len()); 13119625d8cSopenharmony_ci for (i, arg) in self.args.iter().enumerate() { 13219625d8cSopenharmony_ci append_keys(&mut self.keys, arg, i); 13319625d8cSopenharmony_ci } 13419625d8cSopenharmony_ci } 13519625d8cSopenharmony_ci 13619625d8cSopenharmony_ci /// Remove an arg in the graph by Id, usually used by `mut_arg`. Return 13719625d8cSopenharmony_ci /// `Some(arg)` if removed. 13819625d8cSopenharmony_ci pub(crate) fn remove_by_name(&mut self, name: &str) -> Option<Arg> { 13919625d8cSopenharmony_ci self.args 14019625d8cSopenharmony_ci .iter() 14119625d8cSopenharmony_ci .position(|arg| arg.id == name) 14219625d8cSopenharmony_ci // since it's a cold function, using this wouldn't hurt much 14319625d8cSopenharmony_ci .map(|i| self.args.remove(i)) 14419625d8cSopenharmony_ci } 14519625d8cSopenharmony_ci} 14619625d8cSopenharmony_ci 14719625d8cSopenharmony_ciimpl Index<&'_ KeyType> for MKeyMap { 14819625d8cSopenharmony_ci type Output = Arg; 14919625d8cSopenharmony_ci 15019625d8cSopenharmony_ci fn index(&self, key: &KeyType) -> &Self::Output { 15119625d8cSopenharmony_ci self.get(key).expect(INTERNAL_ERROR_MSG) 15219625d8cSopenharmony_ci } 15319625d8cSopenharmony_ci} 15419625d8cSopenharmony_ci 15519625d8cSopenharmony_ci/// Generate key types for an specific Arg. 15619625d8cSopenharmony_cifn append_keys(keys: &mut Vec<Key>, arg: &Arg, index: usize) { 15719625d8cSopenharmony_ci if let Some(pos_index) = arg.index { 15819625d8cSopenharmony_ci let key = KeyType::Position(pos_index); 15919625d8cSopenharmony_ci keys.push(Key { key, index }); 16019625d8cSopenharmony_ci } else { 16119625d8cSopenharmony_ci if let Some(short) = arg.short { 16219625d8cSopenharmony_ci let key = KeyType::Short(short); 16319625d8cSopenharmony_ci keys.push(Key { key, index }); 16419625d8cSopenharmony_ci } 16519625d8cSopenharmony_ci if let Some(long) = arg.long.clone() { 16619625d8cSopenharmony_ci let key = KeyType::Long(long.into()); 16719625d8cSopenharmony_ci keys.push(Key { key, index }); 16819625d8cSopenharmony_ci } 16919625d8cSopenharmony_ci 17019625d8cSopenharmony_ci for (short, _) in arg.short_aliases.iter() { 17119625d8cSopenharmony_ci let key = KeyType::Short(*short); 17219625d8cSopenharmony_ci keys.push(Key { key, index }); 17319625d8cSopenharmony_ci } 17419625d8cSopenharmony_ci for (long, _) in arg.aliases.iter() { 17519625d8cSopenharmony_ci let key = KeyType::Long(long.into()); 17619625d8cSopenharmony_ci keys.push(Key { key, index }); 17719625d8cSopenharmony_ci } 17819625d8cSopenharmony_ci } 17919625d8cSopenharmony_ci} 180