2020-04-27 18:47:08 +00:00
|
|
|
use crate::{build::Arg, util::Id, INTERNAL_ERROR_MSG};
|
|
|
|
|
2020-12-26 17:32:21 +00:00
|
|
|
use std::{ffi::OsString, iter::Iterator, ops::Index};
|
2018-11-14 00:44:43 +00:00
|
|
|
|
|
|
|
#[derive(PartialEq, Debug, Clone)]
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) struct Key {
|
2020-12-26 17:18:43 +00:00
|
|
|
key: KeyType,
|
|
|
|
index: usize,
|
2018-11-14 00:44:43 +00:00
|
|
|
}
|
2018-07-19 12:50:47 +00:00
|
|
|
|
2018-07-26 15:15:47 +00:00
|
|
|
#[derive(Default, PartialEq, Debug, Clone)]
|
2020-07-19 17:11:29 +00:00
|
|
|
pub(crate) struct MKeyMap<'help> {
|
2020-12-26 17:32:21 +00:00
|
|
|
keys: Vec<Key>,
|
|
|
|
args: Vec<Arg<'help>>,
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) enum KeyType {
|
2018-07-19 12:50:47 +00:00
|
|
|
Short(char),
|
2018-07-29 18:20:17 +00:00
|
|
|
Long(OsString),
|
2018-08-01 15:33:55 +00:00
|
|
|
Position(u64),
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|
|
|
|
|
2018-08-21 00:23:52 +00:00
|
|
|
impl KeyType {
|
|
|
|
pub(crate) fn is_position(&self) -> bool {
|
2020-12-24 18:30:37 +00:00
|
|
|
matches!(self, KeyType::Position(_))
|
2018-08-21 00:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-24 18:34:38 +00:00
|
|
|
impl PartialEq<u64> for KeyType {
|
|
|
|
fn eq(&self, rhs: &u64) -> bool {
|
|
|
|
match self {
|
|
|
|
KeyType::Position(x) => x == rhs,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-14 00:44:43 +00:00
|
|
|
impl PartialEq<&str> for KeyType {
|
|
|
|
fn eq(&self, rhs: &&str) -> bool {
|
|
|
|
match self {
|
2020-12-24 18:30:37 +00:00
|
|
|
KeyType::Long(l) => l == rhs,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<OsString> for KeyType {
|
|
|
|
fn eq(&self, rhs: &OsString) -> bool {
|
|
|
|
match self {
|
|
|
|
KeyType::Long(l) => l == rhs,
|
2018-11-14 17:05:06 +00:00
|
|
|
_ => false,
|
2018-11-14 00:44:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq<char> for KeyType {
|
|
|
|
fn eq(&self, rhs: &char) -> bool {
|
|
|
|
match self {
|
|
|
|
KeyType::Short(c) => c == rhs,
|
2018-11-14 17:05:06 +00:00
|
|
|
_ => false,
|
2018-11-14 00:44:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-19 17:11:29 +00:00
|
|
|
impl<'help> MKeyMap<'help> {
|
2020-12-26 16:43:49 +00:00
|
|
|
/// If any arg has corresponding key in this map, we can search the key with
|
|
|
|
/// u64(for positional argument), char(for short flag), &str and OsString
|
|
|
|
/// (for long flag)
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) fn contains<K>(&self, key: K) -> bool
|
2020-01-11 18:15:46 +00:00
|
|
|
where
|
|
|
|
KeyType: PartialEq<K>,
|
|
|
|
{
|
2020-01-09 17:30:22 +00:00
|
|
|
self.keys.iter().any(|x| x.key == key)
|
|
|
|
}
|
2018-11-14 00:44:43 +00:00
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
/// Push an argument in the map.
|
|
|
|
pub(crate) fn push(&mut self, new_arg: Arg<'help>) {
|
|
|
|
self.args.push(new_arg);
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|
2018-07-24 16:48:24 +00:00
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
/// Find the arg have corresponding key in this map, we can search the key
|
|
|
|
/// with u64(for positional argument), char(for short flag), &str and
|
|
|
|
/// OsString (for long flag)
|
2020-12-24 18:30:37 +00:00
|
|
|
pub(crate) fn get<K>(&self, key: &K) -> Option<&Arg<'help>>
|
|
|
|
where
|
|
|
|
KeyType: PartialEq<K>,
|
|
|
|
{
|
2020-01-09 17:30:22 +00:00
|
|
|
self.keys
|
|
|
|
.iter()
|
2020-12-24 18:30:37 +00:00
|
|
|
.find(|k| &k.key == key)
|
2020-01-09 17:30:22 +00:00
|
|
|
.map(|k| &self.args[k.index])
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
/// Find out if the map have no arg.
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) fn is_empty(&self) -> bool {
|
2020-12-26 16:43:49 +00:00
|
|
|
self.args.is_empty()
|
2020-01-31 09:13:44 +00:00
|
|
|
}
|
2018-08-28 01:44:09 +00:00
|
|
|
|
2020-12-26 17:18:43 +00:00
|
|
|
/// Return iterators of all keys.
|
2020-12-26 17:32:21 +00:00
|
|
|
pub(crate) fn keys(&self) -> impl Iterator<Item = &KeyType> {
|
2020-12-26 17:18:43 +00:00
|
|
|
self.keys.iter().map(|x| &x.key)
|
|
|
|
}
|
|
|
|
|
2020-12-26 17:32:21 +00:00
|
|
|
/// Return iterators of all args.
|
|
|
|
pub(crate) fn args(&self) -> impl Iterator<Item = &Arg<'help>> {
|
|
|
|
self.args.iter()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return mutable iterators of all args.
|
|
|
|
pub(crate) fn args_mut<'map>(&'map mut self) -> impl Iterator<Item = &'map mut Arg<'help>> {
|
|
|
|
self.args.iter_mut()
|
|
|
|
}
|
|
|
|
|
2020-03-19 07:17:52 +00:00
|
|
|
pub(crate) fn _build(&mut self) {
|
2018-11-14 00:44:43 +00:00
|
|
|
for (i, arg) in self.args.iter_mut().enumerate() {
|
2018-08-28 00:25:37 +00:00
|
|
|
for k in _get_keys(arg) {
|
2018-11-14 17:05:06 +00:00
|
|
|
self.keys.push(Key { key: k, index: i });
|
2018-08-28 00:25:37 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-01 15:33:55 +00:00
|
|
|
}
|
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
/// Remove an arg in the graph by Id, usually used by `mut_arg`. Return
|
|
|
|
/// `Some(arg)` if removed.
|
2020-07-19 17:11:29 +00:00
|
|
|
pub(crate) fn remove_by_name(&mut self, name: &Id) -> Option<Arg<'help>> {
|
2020-01-09 17:30:22 +00:00
|
|
|
self.args
|
|
|
|
.iter()
|
2020-12-24 18:30:37 +00:00
|
|
|
.position(|arg| &arg.id == name)
|
2020-12-26 16:43:49 +00:00
|
|
|
// since it's a cold function, using this wouldn't hurt much
|
2020-01-09 17:30:22 +00:00
|
|
|
.map(|i| self.args.swap_remove(i))
|
2018-08-28 00:25:37 +00:00
|
|
|
}
|
2018-08-01 15:33:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-19 17:11:29 +00:00
|
|
|
impl<'help> Index<&'_ KeyType> for MKeyMap<'help> {
|
|
|
|
type Output = Arg<'help>;
|
2020-04-25 11:50:17 +00:00
|
|
|
|
2020-07-19 17:11:29 +00:00
|
|
|
fn index(&self, key: &KeyType) -> &Self::Output {
|
2020-04-25 11:50:17 +00:00
|
|
|
self.get(key).expect(INTERNAL_ERROR_MSG)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
/// Generate key types for an specific Arg.
|
2018-11-14 00:44:43 +00:00
|
|
|
fn _get_keys(arg: &Arg) -> Vec<KeyType> {
|
|
|
|
if let Some(index) = arg.index {
|
|
|
|
return vec![KeyType::Position(index)];
|
|
|
|
}
|
2018-07-19 12:50:47 +00:00
|
|
|
|
2018-11-14 00:44:43 +00:00
|
|
|
let mut keys = vec![];
|
2020-05-04 18:01:11 +00:00
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
if let Some(short) = arg.short {
|
|
|
|
keys.push(KeyType::Short(short));
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|
2018-11-14 00:44:43 +00:00
|
|
|
if let Some(long) = arg.long {
|
|
|
|
keys.push(KeyType::Long(OsString::from(long)));
|
|
|
|
}
|
|
|
|
|
2020-12-26 16:43:49 +00:00
|
|
|
for (short, _) in arg.short_aliases.iter() {
|
|
|
|
keys.push(KeyType::Short(*short));
|
|
|
|
}
|
|
|
|
for (long, _) in arg.aliases.iter() {
|
|
|
|
keys.push(KeyType::Long(OsString::from(long)));
|
|
|
|
}
|
2018-11-14 00:44:43 +00:00
|
|
|
keys
|
2018-07-19 12:50:47 +00:00
|
|
|
}
|