Skip to main content

fpr_cli/
parse.rs

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}
81impl<'a> Display for ArgsErr<'a> {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        use ArgsErr::*;
84        let e = match self {
85            Run(e) => e.to_string(),
86            Parse(e) => e.to_string(),
87        };
88        write!(f, "{e}")
89    }
90}
91
92pub const PFX: &'static str = "--";
93#[derive(Debug)]
94pub struct Key<'a> {
95    pub k: Option<&'a str>,
96    pub v: Vec<&'a str>,
97    pub used: bool,
98}
99#[derive(Debug)]
100pub struct ParsedArgs<'c> {
101    pub k: Vec<Key<'c>>,
102}
103
104impl<'c> ParsedArgs<'c> {
105    pub fn consume(&mut self, name: &str) -> Option<&Vec<&'c str>> {
106        let k = self
107            .k
108            .iter_mut()
109            .find(|k| k.k.map(|k| k == name).unwrap_or(false))?;
110        assert!(
111            !k.used,
112            "A token should not ever be consumed twice. Probably a duplicate argument: {name}"
113        );
114        k.used = true;
115        Some(&k.v)
116    }
117}
118
119pub enum ParsedArgsErr<'a> {
120    UnexpectedToken(Arg<'a>),
121}
122impl<'c> ParsedArgs<'c> {
123    pub fn new(args: &[&'c str]) -> Result<ParsedArgs<'c>, ParsedArgsErr<'c>> {
124        let mut last: Option<&str> = None;
125        let r = ParsedArgs {
126            k: args
127                .iter()
128                .filter_map(|a| {
129                    if a.starts_with(PFX) {
130                        last = Some(a);
131                        None
132                    } else {
133                        Some((last, *a))
134                    }
135                })
136                .into_group_map()
137                .into_iter()
138                .map(|(k, v)| Key { k, v, used: false })
139                .collect(),
140        };
141
142        Ok(r)
143    }
144}
145
146pub enum Init<C, T: Display> {
147    None,
148    Const(T),
149    Dyn(fn(&C) -> T),
150}
151
152impl<C, T: Display> Init<C, T> {
153    pub fn get(self, c: &C) -> Option<T> {
154        match self {
155            Init::None => None,
156            Init::Const(v) => Some(v),
157            Init::Dyn(f) => Some(f(&c)),
158        }
159    }
160    fn to_string(self, c: &C) -> String {
161        match self.get(c) {
162            Some(s) => format!(" (default: {s})"),
163            None => format!(""),
164        }
165    }
166}
167
168pub trait Parse2<'a, 'b, C>
169where
170    Self: Sized,
171    Self::I: Display,
172{
173    type I;
174    fn parse2(
175        i: Init<C, Self::I>,
176        k: &'static str,
177        c: &C,
178        p: &mut ParsedArgs<'b>,
179    ) -> Result<Self, ArgParseErr<'b>>;
180    fn desc2(i: Init<C, Self::I>, d: &'static str, k: &'static str, c: &C) -> [String; 4];
181    fn default2(c: &C, i: Init<C, Self::I>) -> Self;
182}
183
184impl<'a, 'b, C, T: Parse<'a> + Default> Parse2<'b, 'a, C> for T {
185    type I = T;
186    fn parse2(
187        i: Init<C, Self::I>,
188        k: &'static str,
189        c: &C,
190        p: &mut ParsedArgs<'a>,
191    ) -> Result<Self, ArgParseErr<'a>> {
192        match p.consume(k) {
193            Some(args) => {
194                if args.len() != 1 {
195                    Err(Parse2Err::ExpectedOne)?
196                } else {
197                    Ok(T::parse(&args[0])?)
198                }
199            }
200            None => Ok(i.get(c).ok_or(Parse2Err::Rquired)?),
201        }
202    }
203
204    fn desc2(i: Init<C, Self>, d: &'static str, k: &'static str, c: &C) -> [String; 4] {
205        [
206            k.into(),
207            format!("Req<{}>", T::desc()),
208            d.into(),
209            i.to_string(c),
210        ]
211    }
212    fn default2(c: &C, i: Init<C, Self::I>) -> Self {
213        i.get(c).unwrap_or(Self::default())
214    }
215}
216
217impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for Option<T> {
218    type I = T;
219    fn parse2(
220        i: Init<Ctx, T>,
221        k: &'static str,
222        c: &Ctx,
223        p: &mut ParsedArgs<'a>,
224    ) -> Result<Self, ArgParseErr<'a>> {
225        match p.consume(k) {
226            Some(args) => {
227                if args.len() != 1 {
228                    Err(Parse2Err::ExpectedOne)?
229                } else {
230                    Ok(Some(T::parse(&args[0])?))
231                }
232            }
233            None => Ok(match i.get(c) {
234                Some(e) => Some(e),
235                None => None,
236            }),
237        }
238    }
239    fn desc2(i: Init<Ctx, T>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
240        [
241            k.into(),
242            format!("Opt<{}>", T::desc()),
243            d.into(),
244            i.to_string(c),
245        ]
246    }
247    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
248        match i.get(c) {
249            Some(i) => Some(i),
250            None => None,
251        }
252    }
253}
254
255impl<'a, 'b, Ctx, T: Parse<'a> + Display> Parse2<'b, 'a, Ctx> for Vec<T> {
256    type I = DisplayVec<T>;
257    fn parse2(
258        i: Init<Ctx, Self::I>,
259        k: &'static str,
260        c: &Ctx,
261        p: &mut ParsedArgs<'a>,
262    ) -> Result<Self, ArgParseErr<'a>> {
263        match p.consume(k) {
264            Some(args) => {
265                let args = args
266                    .iter()
267                    .map(|a| T::parse(a))
268                    .collect::<Result<Vec<_>, _>>()?;
269                if args.is_empty() {
270                    Err(Parse2Err::ExpectedAtLeastOne)?
271                }
272                Ok(args)
273            }
274            None => Ok(match i.get(c) {
275                Some(e) => e.into(),
276                None => vec![],
277            }),
278        }
279    }
280
281    fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
282        [
283            k.into(),
284            format!("Vec<{}>", T::desc()),
285            d.into(),
286            i.to_string(c),
287        ]
288    }
289    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
290        match i.get(c) {
291            Some(v) => v.0,
292            None => Self::default(),
293        }
294    }
295}
296
297#[derive(Debug)]
298pub struct OptVec<T: Display>(pub Vec<T>);
299impl<T: Display> From<Vec<T>> for OptVec<T> {
300    fn from(v: Vec<T>) -> Self {
301        Self(v)
302    }
303}
304impl<T: Display> From<DisplayVec<T>> for OptVec<T> {
305    fn from(v: DisplayVec<T>) -> Self {
306        Self(v.0)
307    }
308}
309impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for OptVec<T> {
310    type I = DisplayVec<T>;
311    fn parse2(
312        i: Init<Ctx, Self::I>,
313        k: &'static str,
314        c: &Ctx,
315        p: &mut ParsedArgs<'a>,
316    ) -> Result<Self, ArgParseErr<'a>> {
317        match p.consume(k) {
318            Some(args) => {
319                let args = args
320                    .iter()
321                    .map(|a| T::parse(a))
322                    .collect::<Result<Vec<_>, _>>()?;
323                Ok(args.into())
324            }
325            None => Ok(match i.get(c) {
326                Some(e) => e.into(),
327                None => vec![].into(),
328            }),
329        }
330    }
331
332    fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
333        [
334            k.into(),
335            format!("Vec<{}>", T::desc()),
336            d.into(),
337            i.to_string(c),
338        ]
339    }
340    fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
341        Self::from(match i.get(c) {
342            Some(v) => v.0,
343            None => <Vec<T>>::default(),
344        })
345    }
346}
347impl Display for DirExist {
348    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
349        write!(f, "{}", self.s)
350    }
351}
352impl Display for FileExist {
353    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354        write!(f, "{}", self.s)
355    }
356}