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