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