1 use std
::iter
::Iterator
;
3 use std
::{ffi::OsStr, ffi::OsString}
;
7 use crate::INTERNAL_ERROR_MSG
;
9 #[derive(PartialEq, Eq, Debug, Clone)]
10 pub(crate) struct Key
{
15 #[derive(Default, PartialEq, Eq, Debug, Clone)]
16 pub(crate) struct MKeyMap
<'help
> {
17 /// All of the arguments.
18 args
: Vec
<Arg
<'help
>>,
21 /// Will be set after `_build()`.
25 #[derive(Debug, PartialEq, Eq, Hash, Clone)]
26 pub(crate) enum KeyType
{
33 pub(crate) fn is_position(&self) -> bool
{
34 matches
!(self, KeyType
::Position(_
))
38 impl PartialEq
<usize> for KeyType
{
39 fn eq(&self, rhs
: &usize) -> bool
{
41 KeyType
::Position(x
) => x
== rhs
,
47 impl PartialEq
<&str> for KeyType
{
48 fn eq(&self, rhs
: &&str) -> bool
{
50 KeyType
::Long(l
) => l
== rhs
,
56 impl PartialEq
<str> for KeyType
{
57 fn eq(&self, rhs
: &str) -> bool
{
59 KeyType
::Long(l
) => l
== rhs
,
65 impl PartialEq
<OsStr
> for KeyType
{
66 fn eq(&self, rhs
: &OsStr
) -> bool
{
68 KeyType
::Long(l
) => l
== rhs
,
74 impl PartialEq
<char> for KeyType
{
75 fn eq(&self, rhs
: &char) -> bool
{
77 KeyType
::Short(c
) => c
== rhs
,
83 impl<'help
> MKeyMap
<'help
> {
84 /// If any arg has corresponding key in this map, we can search the key with
85 /// u64(for positional argument), char(for short flag), &str and OsString
87 pub(crate) fn contains
<K
>(&self, key
: K
) -> bool
89 KeyType
: PartialEq
<K
>,
91 self.keys
.iter().any(|x
| x
.key
== key
)
94 /// Reserves capacity for at least additional more elements to be inserted
95 pub(crate) fn reserve(&mut self, additional
: usize) {
96 self.args
.reserve(additional
);
99 /// Push an argument in the map.
100 pub(crate) fn push(&mut self, new_arg
: Arg
<'help
>) {
101 self.args
.push(new_arg
);
104 /// Find the arg have corresponding key in this map, we can search the key
105 /// with u64(for positional argument), char(for short flag), &str and
106 /// OsString (for long flag)
107 pub(crate) fn get
<K
: ?Sized
>(&self, key
: &K
) -> Option
<&Arg
<'help
>>
109 KeyType
: PartialEq
<K
>,
113 .find(|k
| &k
.key
== key
)
114 .map(|k
| &self.args
[k
.index
])
117 /// Find out if the map have no arg.
118 pub(crate) fn is_empty(&self) -> bool
{
122 /// Return iterators of all keys.
123 pub(crate) fn keys(&self) -> impl Iterator
<Item
= &KeyType
> {
124 self.keys
.iter().map(|x
| &x
.key
)
127 /// Return iterators of all args.
128 pub(crate) fn args(&self) -> impl Iterator
<Item
= &Arg
<'help
>> {
132 /// Return mutable iterators of all args.
133 pub(crate) fn args_mut
<'map
>(&'map
mut self) -> impl Iterator
<Item
= &'map
mut Arg
<'help
>> {
137 /// We need a lazy build here since some we may change args after creating
138 /// the map, you can checkout who uses `args_mut`.
139 pub(crate) fn _build(&mut self) {
140 for (i
, arg
) in self.args
.iter().enumerate() {
141 append_keys(&mut self.keys
, arg
, i
);
145 /// Remove an arg in the graph by Id, usually used by `mut_arg`. Return
146 /// `Some(arg)` if removed.
147 pub(crate) fn remove_by_name(&mut self, name
: &Id
) -> Option
<Arg
<'help
>> {
150 .position(|arg
| &arg
.id
== name
)
151 // since it's a cold function, using this wouldn't hurt much
152 .map(|i
| self.args
.remove(i
))
155 /// Remove an arg based on index
156 pub(crate) fn remove(&mut self, index
: usize) -> Arg
<'help
> {
157 self.args
.remove(index
)
161 impl<'help
> Index
<&'_ KeyType
> for MKeyMap
<'help
> {
162 type Output
= Arg
<'help
>;
164 fn index(&self, key
: &KeyType
) -> &Self::Output
{
165 self.get(key
).expect(INTERNAL_ERROR_MSG
)
169 /// Generate key types for an specific Arg.
170 fn append_keys(keys
: &mut Vec
<Key
>, arg
: &Arg
, index
: usize) {
171 if let Some(pos_index
) = arg
.index
{
172 let key
= KeyType
::Position(pos_index
);
173 keys
.push(Key { key, index }
);
175 if let Some(short
) = arg
.short
{
176 let key
= KeyType
::Short(short
);
177 keys
.push(Key { key, index }
);
179 if let Some(long
) = arg
.long
{
180 let key
= KeyType
::Long(OsString
::from(long
));
181 keys
.push(Key { key, index }
);
184 for (short
, _
) in arg
.short_aliases
.iter() {
185 let key
= KeyType
::Short(*short
);
186 keys
.push(Key { key, index }
);
188 for (long
, _
) in arg
.aliases
.iter() {
189 let key
= KeyType
::Long(OsString
::from(long
));
190 keys
.push(Key { key, index }
);