1pub const NUM_VALUES: usize = 16;
2pub type Values<'a> = [&'a str; NUM_VALUES];
3
4
5#[derive(Clone, Copy, PartialEq, Eq, Debug)]
6enum NumArgs {
7 None,
8 All,
9 Number(u32)
10}
11
12
13#[derive(Clone, Copy, PartialEq, Eq, Debug)]
14enum ArgName<'a> {
15 Name(&'a str),
16 Flag(&'a str)
17}
18
19
20#[derive(Clone, Copy, PartialEq, Eq, Debug)]
21pub struct Arg<'a> {
22 name: ArgName<'a>,
23 num_args: NumArgs,
24 matched_data: Values<'a>
25}
26
27
28pub fn args<'a>(a: &[&'a str]) -> Values<'a> {
30 let mut result = [""; NUM_VALUES];
31 for (i, arg) in a.clone().iter().enumerate() {
32 result[i] = arg.clone();
33 }
34 result
35}
36
37
38fn to_argname<'a>(name: &'a str) -> ArgName<'a> {
39 if let Some(ch) = name.chars().nth(0) {
40 match ch {
41 '-' => {
42 ArgName::Flag(name)
43 },
44 _ => {
45 ArgName::Name(name)
46 }
47 }
48 } else {
49 ArgName::Name(name)
50 }
51}
52
53impl<'a> Arg<'a> {
54 pub fn new(name: &'a str) -> Self {
55 Self {
56 name: to_argname(name),
57 num_args: NumArgs::Number(1),
58 matched_data: [""; NUM_VALUES]
59 }
60 }
61
62 pub fn has_name(&self, name: &'a str) -> bool {
64 to_argname(name) == self.name
65 }
66
67 pub fn is_flag(&self) -> bool {
69 match self.name {
70 ArgName::Name(_) => false,
71 ArgName::Flag(_) => true
72 }
73 }
74
75 pub fn num_values(mut self, n: i32) -> Self {
77 if let ArgName::Flag(_) = self.name {
78 self.num_args = match n {
79 -1 => NumArgs::All,
80 0 => NumArgs::None,
81 n => NumArgs::Number(n as u32),
82 };
83 }
84
85 self
86 }
87
88 pub fn get_values(&self) -> Values<'a> {
89 self.matched_data
90 }
91
92 pub fn is_match(&self, slice_matches: &[&'a str]) -> bool {
96 if self.has_name("") { return false; }
98
99 let matches = args(slice_matches);
101
102 if self.matched_data[0] != "" { return false; }
104
105 let mut num_args = 0;
107 for m in matches.iter() {
108 if m.clone() != "" { num_args += 1; }
109 }
110
111 match self.name {
114 ArgName::Name(_) => {
115 let valid_num_args = match self.num_args {
116 NumArgs::Number(1) => num_args == 1,
118 NumArgs::All | NumArgs::Number(_) | NumArgs::None => false,
120 };
121
122 valid_num_args
123 },
124 ArgName::Flag(n) => {
125 let valid_num_args = match self.num_args {
126 NumArgs::None => num_args == 1,
127 NumArgs::All => true,
128 NumArgs::Number(n) => num_args == n + 1
129 };
130
131 valid_num_args && (matches[0] == n)
132 }
133 }
134 }
135
136 pub fn consume<'b>(&mut self, values: &'b mut Values<'a>) -> bool {
139 let mut matched_up_to = 0;
140 let mut consumed = false;
141
142 for n in (1..values.len()).rev() {
143 if (*values)[n-1] == "" {
144 continue;
145 }
146
147 if self.is_match(&values[0..n]) {
148
149 if self.is_flag() {
150 self.matched_data = args(&values[1..n]);
151 } else {
152 self.matched_data = args(&values[0..n]);
153 }
154 matched_up_to = n;
155
156 consumed = true;
157 }
158 }
159
160 *values = args(&values[matched_up_to..]);
161 consumed
162 }
163}