1use crate::com::*;
2
3pub enum Parse2Err {
4 ExpectedOne,
5 Rquired,
6 ExpectedAtLeastOne,
7}
8pub enum ArgParseErr<'a> {
9 ParseErr(ParseErr<'a>),
10 Parse2Err(Parse2Err),
11}
12impl<'a> From<ParseErr<'a>> for ArgParseErr<'a> {
13 fn from(v: ParseErr<'a>) -> Self {
14 ArgParseErr::ParseErr(v)
15 }
16}
17impl<'a> From<Parse2Err> for ArgParseErr<'a> {
18 fn from(v: Parse2Err) -> Self {
19 ArgParseErr::Parse2Err(v)
20 }
21}
22pub enum ArgsParseErr<'a> {
23 UnexpectedToken(Arg<'a>, String),
24 Help(String),
25 UnknownArgs(Vec<Arg<'a>>, String),
26 Arg(&'static str, ArgParseErr<'a>, String),
27}
28impl<'a> Display for ArgsParseErr<'a> {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 use ArgsParseErr::*;
31 match self {
32 UnexpectedToken(ref a, _) => write!(f, "Unexpected token '{a}'")?,
33 Help(_) => (),
34 UnknownArgs(ref a, _) => write!(
35 f,
36 "Unknown options '{}'",
37 a.into_iter().map(|a| format!(r#""{a}""#)).join(", ")
38 )?,
39 Arg(ref a, ref e, _) => write!(f, "Error parsing option '{a}.'\n{e}")?,
40 };
41 Ok(())
42 }
43}
44impl<'a> Display for ArgParseErr<'a> {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 use ArgParseErr::*;
47 match self {
48 ParseErr(e) => write!(f, "{e}"),
49 Parse2Err(e) => write!(f, "{e}"),
50 }
51 }
52}
53impl<'a> Display for ParseErr<'a> {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(
56 f,
57 "Failed to parse '{}' as '{}' because '{}'",
58 self.i, self.ty, self.e
59 )
60 }
61}
62impl Display for Parse2Err {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 use Parse2Err::*;
65 match self {
66 ExpectedOne => write!(f, "Expected one value."),
67 Rquired => write!(f, "Required."),
68 ExpectedAtLeastOne => write!(f, "Expected one value minimum."),
69 }
70 }
71}
72pub enum ArgsErr<'a> {
73 Run(String),
74 Parse(ArgsParseErr<'a>),
75}
76impl<'a> From<ArgsParseErr<'a>> for ArgsErr<'a> {
77 fn from(v: ArgsParseErr<'a>) -> Self {
78 Self::Parse(v)
79 }
80}
81
82pub const PFX: &'static str = "--";
83#[derive(Debug)]
84pub struct Key {
85 pub i: usize,
86 pub used: bool,
87}
88#[derive(Debug)]
89pub struct ParsedArgs<'b, 'c> {
90 pub args: &'b [&'c str],
91 pub keys: Vec<Key>,
92}
93
94impl<'b, 'c> ParsedArgs<'b, 'c> {
95 pub fn consume(&mut self, name: &str) -> Option<&[&'c str]> {
96 let (i, k) = self
97 .keys
98 .iter_mut()
99 .enumerate()
100 .find(|(_, k)| self.args[k.i] == name)?;
101 assert!(
102 !k.used,
103 "A token should not ever be consumed twice. Probably a duplicate argument: {name}"
104 );
105 k.used = true;
106 let idx = k.i + 1;
107 Some(if i == self.keys.len() - 1 {
108 &self.args[idx..]
109 } else if self.args[self.keys[i + 1].i] == PFX {
110 &self.args[self.keys[i + 1].i + 1..]
111 } else {
112 &self.args[idx..self.keys[i + 1].i]
113 })
114 }
115}
116
117pub enum ParsedArgsErr<'a> {
118 UnexpectedToken(Arg<'a>),
119}
120impl<'b, 'c> ParsedArgs<'b, 'c> {
121 pub fn new(args: &'b [&'c str]) -> Result<ParsedArgs<'b, 'c>, ParsedArgsErr<'c>> {
122 let mut end = false;
123 let r = ParsedArgs {
124 args,
125 keys: args
126 .iter()
127 .enumerate()
128 .filter(|&(_, a)| {
129 if end {
130 false
131 } else {
132 let pfx = a.starts_with(PFX);
133 if pfx && a.len() == PFX.len() {
134 end = true;
135 true
136 } else {
137 pfx
138 }
139 }
140 })
141 .map(|(i, _)| Key { i, used: false })
142 .collect(),
143 };
144
145 if !r.keys.is_empty() && r.keys[0].i != 0 {
146 Err(ParsedArgsErr::UnexpectedToken(args[0]))
147 } else {
148 Ok(r)
149 }
150 }
151}
152
153pub enum Init<C, T: Display> {
154 None,
155 Const(T),
156 Dyn(fn(&C) -> T),
157}
158
159impl<C, T: Display> Init<C, T> {
160 pub fn get(self, c: &C) -> Option<T> {
161 match self {
162 Init::None => None,
163 Init::Const(v) => Some(v),
164 Init::Dyn(f) => Some(f(&c)),
165 }
166 }
167 fn to_string(self, c: &C) -> String {
168 match self.get(c) {
169 Some(s) => format!(" (default: {s})"),
170 None => format!(""),
171 }
172 }
173}
174
175pub trait Parse2<'a, 'b, C>
176where
177 Self: Sized,
178 Self::I: Display,
179{
180 type I;
181 fn parse2(
182 i: Init<C, Self::I>,
183 k: &'static str,
184 c: &C,
185 p: &mut ParsedArgs<'a, 'b>,
186 ) -> Result<Self, ArgParseErr<'b>>;
187 fn desc2(i: Init<C, Self::I>, d: &'static str, k: &'static str, c: &C) -> [String; 4];
188 fn default2(c: &C, i: Init<C, Self::I>) -> Self;
189}
190
191impl<'a, 'b, C, T: Parse<'a> + Default> Parse2<'b, 'a, C> for T {
192 type I = T;
193 fn parse2(
194 i: Init<C, Self::I>,
195 k: &'static str,
196 c: &C,
197 p: &mut ParsedArgs<'b, 'a>,
198 ) -> Result<Self, ArgParseErr<'a>> {
199 match p.consume(k) {
200 Some(args) => {
201 if args.len() != 1 {
202 Err(Parse2Err::ExpectedOne)?
203 } else {
204 Ok(T::parse(&args[0])?)
205 }
206 }
207 None => Ok(i.get(c).ok_or(Parse2Err::Rquired)?),
208 }
209 }
210
211 fn desc2(i: Init<C, Self>, d: &'static str, k: &'static str, c: &C) -> [String; 4] {
212 [
213 k.into(),
214 format!("Req<{}>", T::desc()),
215 d.into(),
216 i.to_string(c),
217 ]
218 }
219 fn default2(c: &C, i: Init<C, Self::I>) -> Self {
220 i.get(c).unwrap_or(Self::default())
221 }
222}
223
224impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for Option<T> {
225 type I = T;
226 fn parse2(
227 i: Init<Ctx, T>,
228 k: &'static str,
229 c: &Ctx,
230 p: &mut ParsedArgs<'b, 'a>,
231 ) -> Result<Self, ArgParseErr<'a>> {
232 match p.consume(k) {
233 Some(args) => {
234 if args.len() != 1 {
235 Err(Parse2Err::ExpectedOne)?
236 } else {
237 Ok(Some(T::parse(&args[0])?))
238 }
239 }
240 None => Ok(match i.get(c) {
241 Some(e) => Some(e),
242 None => None,
243 }),
244 }
245 }
246 fn desc2(i: Init<Ctx, T>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
247 [
248 k.into(),
249 format!("Opt<{}>", T::desc()),
250 d.into(),
251 i.to_string(c),
252 ]
253 }
254 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
255 match i.get(c) {
256 Some(i) => Some(i),
257 None => None,
258 }
259 }
260}
261
262impl<'a, 'b, Ctx, T: Parse<'a> + Display> Parse2<'b, 'a, Ctx> for Vec<T> {
263 type I = DisplayVec<T>;
264 fn parse2(
265 i: Init<Ctx, Self::I>,
266 k: &'static str,
267 c: &Ctx,
268 p: &mut ParsedArgs<'b, 'a>,
269 ) -> Result<Self, ArgParseErr<'a>> {
270 match p.consume(k) {
271 Some(args) => {
272 let args = args
273 .iter()
274 .map(|a| T::parse(a))
275 .collect::<Result<Vec<_>, _>>()?;
276 if args.is_empty() {
277 Err(Parse2Err::ExpectedAtLeastOne)?
278 }
279 Ok(args)
280 }
281 None => Ok(match i.get(c) {
282 Some(e) => e.into(),
283 None => vec![],
284 }),
285 }
286 }
287
288 fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
289 [
290 k.into(),
291 format!("Vec<{}>", T::desc()),
292 d.into(),
293 i.to_string(c),
294 ]
295 }
296 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
297 match i.get(c) {
298 Some(v) => v.0,
299 None => Self::default(),
300 }
301 }
302}
303
304pub struct OptVec<T: Display>(pub Vec<T>);
305impl<T: Display> From<Vec<T>> for OptVec<T> {
306 fn from(v: Vec<T>) -> Self {
307 Self(v)
308 }
309}
310impl<T: Display> From<DisplayVec<T>> for OptVec<T> {
311 fn from(v: DisplayVec<T>) -> Self {
312 Self(v.0)
313 }
314}
315impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for OptVec<T> {
316 type I = DisplayVec<T>;
317 fn parse2(
318 i: Init<Ctx, Self::I>,
319 k: &'static str,
320 c: &Ctx,
321 p: &mut ParsedArgs<'b, 'a>,
322 ) -> Result<Self, ArgParseErr<'a>> {
323 match p.consume(k) {
324 Some(args) => {
325 let args = args
326 .iter()
327 .map(|a| T::parse(a))
328 .collect::<Result<Vec<_>, _>>()?;
329 Ok(args.into())
330 }
331 None => Ok(match i.get(c) {
332 Some(e) => e.into(),
333 None => vec![].into(),
334 }),
335 }
336 }
337
338 fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
339 [
340 k.into(),
341 format!("Vec<{}>", T::desc()),
342 d.into(),
343 i.to_string(c),
344 ]
345 }
346 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
347 Self::from(match i.get(c) {
348 Some(v) => v.0,
349 None => <Vec<T>>::default(),
350 })
351 }
352}
353impl Display for DirExist {
354 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355 write!(f, "{}", self.s)
356 }
357}
358impl Display for FileExist {
359 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360 write!(f, "{}", self.s)
361 }
362}