]> git.proxmox.com Git - rustc.git/blob - vendor/clap-3.2.20/src/mkeymap.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / clap-3.2.20 / src / mkeymap.rs
1 use std::iter::Iterator;
2 use std::ops::Index;
3 use std::{ffi::OsStr, ffi::OsString};
4
5 use crate::util::Id;
6 use crate::Arg;
7 use crate::INTERNAL_ERROR_MSG;
8
9 #[derive(PartialEq, Eq, Debug, Clone)]
10 pub(crate) struct Key {
11 key: KeyType,
12 index: usize,
13 }
14
15 #[derive(Default, PartialEq, Eq, Debug, Clone)]
16 pub(crate) struct MKeyMap<'help> {
17 /// All of the arguments.
18 args: Vec<Arg<'help>>,
19
20 // Cache part:
21 /// Will be set after `_build()`.
22 keys: Vec<Key>,
23 }
24
25 #[derive(Debug, PartialEq, Eq, Hash, Clone)]
26 pub(crate) enum KeyType {
27 Short(char),
28 Long(OsString),
29 Position(usize),
30 }
31
32 impl KeyType {
33 pub(crate) fn is_position(&self) -> bool {
34 matches!(self, KeyType::Position(_))
35 }
36 }
37
38 impl PartialEq<usize> for KeyType {
39 fn eq(&self, rhs: &usize) -> bool {
40 match self {
41 KeyType::Position(x) => x == rhs,
42 _ => false,
43 }
44 }
45 }
46
47 impl PartialEq<&str> for KeyType {
48 fn eq(&self, rhs: &&str) -> bool {
49 match self {
50 KeyType::Long(l) => l == rhs,
51 _ => false,
52 }
53 }
54 }
55
56 impl PartialEq<str> for KeyType {
57 fn eq(&self, rhs: &str) -> bool {
58 match self {
59 KeyType::Long(l) => l == rhs,
60 _ => false,
61 }
62 }
63 }
64
65 impl PartialEq<OsStr> for KeyType {
66 fn eq(&self, rhs: &OsStr) -> bool {
67 match self {
68 KeyType::Long(l) => l == rhs,
69 _ => false,
70 }
71 }
72 }
73
74 impl PartialEq<char> for KeyType {
75 fn eq(&self, rhs: &char) -> bool {
76 match self {
77 KeyType::Short(c) => c == rhs,
78 _ => false,
79 }
80 }
81 }
82
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
86 /// (for long flag)
87 pub(crate) fn contains<K>(&self, key: K) -> bool
88 where
89 KeyType: PartialEq<K>,
90 {
91 self.keys.iter().any(|x| x.key == key)
92 }
93
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);
97 }
98
99 /// Push an argument in the map.
100 pub(crate) fn push(&mut self, new_arg: Arg<'help>) {
101 self.args.push(new_arg);
102 }
103
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>>
108 where
109 KeyType: PartialEq<K>,
110 {
111 self.keys
112 .iter()
113 .find(|k| &k.key == key)
114 .map(|k| &self.args[k.index])
115 }
116
117 /// Find out if the map have no arg.
118 pub(crate) fn is_empty(&self) -> bool {
119 self.args.is_empty()
120 }
121
122 /// Return iterators of all keys.
123 pub(crate) fn keys(&self) -> impl Iterator<Item = &KeyType> {
124 self.keys.iter().map(|x| &x.key)
125 }
126
127 /// Return iterators of all args.
128 pub(crate) fn args(&self) -> impl Iterator<Item = &Arg<'help>> {
129 self.args.iter()
130 }
131
132 /// Return mutable iterators of all args.
133 pub(crate) fn args_mut<'map>(&'map mut self) -> impl Iterator<Item = &'map mut Arg<'help>> {
134 self.args.iter_mut()
135 }
136
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);
142 }
143 }
144
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>> {
148 self.args
149 .iter()
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))
153 }
154
155 /// Remove an arg based on index
156 pub(crate) fn remove(&mut self, index: usize) -> Arg<'help> {
157 self.args.remove(index)
158 }
159 }
160
161 impl<'help> Index<&'_ KeyType> for MKeyMap<'help> {
162 type Output = Arg<'help>;
163
164 fn index(&self, key: &KeyType) -> &Self::Output {
165 self.get(key).expect(INTERNAL_ERROR_MSG)
166 }
167 }
168
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 });
174 } else {
175 if let Some(short) = arg.short {
176 let key = KeyType::Short(short);
177 keys.push(Key { key, index });
178 }
179 if let Some(long) = arg.long {
180 let key = KeyType::Long(OsString::from(long));
181 keys.push(Key { key, index });
182 }
183
184 for (short, _) in arg.short_aliases.iter() {
185 let key = KeyType::Short(*short);
186 keys.push(Key { key, index });
187 }
188 for (long, _) in arg.aliases.iter() {
189 let key = KeyType::Long(OsString::from(long));
190 keys.push(Key { key, index });
191 }
192 }
193 }