1use crate::com::*;
2
3pub const PFX: &'static str = "--";
4#[derive(Debug)]
5pub struct Key<'a> {
6 pub k: Option<&'a str>,
7 pub v: Vec<&'a str>,
8 pub used: bool,
9}
10#[derive(Debug)]
11pub struct ParsedArgs<'c> {
12 pub k: Vec<Key<'c>>,
13}
14
15impl<'c> ParsedArgs<'c> {
16 pub fn consume(&mut self, name: &str) -> Option<&Vec<&'c str>> {
17 let k = self
18 .k
19 .iter_mut()
20 .find(|k| k.k.map(|k| k == name).unwrap_or(false))?;
21 assert!(
22 !k.used,
23 "A token should not ever be consumed twice. Probably a duplicate argument: {name}"
24 );
25 k.used = true;
26 Some(&k.v)
27 }
28}
29
30impl<'c> ParsedArgs<'c> {
31 pub fn new(args: &[&'c str]) -> Self {
32 let mut last: Option<&str> = None;
33 let r = ParsedArgs {
34 k: args
35 .iter()
36 .map(|a| {
37 if a.starts_with(PFX) {
38 last = Some(a);
39 }
40 (last, *a)
41 })
42 .into_group_map()
43 .into_iter()
44 .map(|(k, v)| Key {
45 k,
46 v: if k.is_some() { v[1..].into() } else { v },
47 used: false,
48 })
49 .collect(),
50 };
51
52 r
53 }
54}
55
56pub enum Init<C, T: Display> {
57 None,
58 Const(T),
59 Dyn(fn(&C) -> T),
60}
61
62impl<C, T: Display> Init<C, T> {
63 pub fn get(self, c: &C) -> Option<T> {
64 match self {
65 Init::None => None,
66 Init::Const(v) => Some(v),
67 Init::Dyn(f) => Some(f(&c)),
68 }
69 }
70 fn to_string(self, c: &C) -> String {
71 match self.get(c) {
72 Some(s) => format!(" (default: {s})"),
73 None => format!(""),
74 }
75 }
76}
77
78#[derive(Error, Debug)]
79pub enum ErrArg {
80 #[error("Failed while parsing values for '{arg}': {e}")]
81 Val { arg: String, e: ErrVal },
82 #[error("'{arg}' must be one value.")]
83 OnlyOne { arg: String },
84 #[error("'{arg}' is required.")]
85 Required { arg: String },
86 #[error("'{arg}' requires at least one value.")]
87 AtLeastOne { arg: String },
88}
89
90pub trait Parse2<'a, 'b, C>
91where
92 Self: Sized,
93 Self::I: Display,
94{
95 type I;
96 fn parse2(
97 i: Init<C, Self::I>,
98 k: &'static str,
99 c: &C,
100 p: &mut ParsedArgs<'b>,
101 ) -> Result<Self, ErrArg>;
102 fn desc2(i: Init<C, Self::I>, d: &'static str, k: &'static str, c: &C) -> [String; 4];
103 fn default2(c: &C, i: Init<C, Self::I>) -> Self;
104}
105
106impl<'a, 'b, C, T: Parse<'a> + Default> Parse2<'b, 'a, C> for T {
107 type I = T;
108 fn parse2(
109 i: Init<C, Self::I>,
110 k: &'static str,
111 c: &C,
112 p: &mut ParsedArgs<'a>,
113 ) -> Result<Self, ErrArg> {
114 match p.consume(k) {
115 Some(args) => {
116 if args.len() != 1 {
117 Err(ErrArg::OnlyOne { arg: k.into() })
118 } else {
119 Ok(T::parse(&args[0]).map_err(|e| ErrArg::Val { arg: k.into(), e })?)
120 }
121 }
122 None => Ok(i.get(c).ok_or(ErrArg::Required { arg: k.into() })?),
123 }
124 }
125
126 fn desc2(i: Init<C, Self>, d: &'static str, k: &'static str, c: &C) -> [String; 4] {
127 [
128 k.into(),
129 format!("Req<{}>", T::desc()),
130 d.into(),
131 i.to_string(c),
132 ]
133 }
134 fn default2(c: &C, i: Init<C, Self::I>) -> Self {
135 i.get(c).unwrap_or(Self::default())
136 }
137}
138
139impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for Option<T> {
140 type I = T;
141 fn parse2(
142 i: Init<Ctx, T>,
143 k: &'static str,
144 c: &Ctx,
145 p: &mut ParsedArgs<'a>,
146 ) -> Result<Self, ErrArg> {
147 match p.consume(k) {
148 Some(args) => {
149 if args.len() != 1 {
150 Err(ErrArg::OnlyOne { arg: k.into() })
151 } else {
152 Ok(Some(
153 T::parse(&args[0]).map_err(|e| ErrArg::Val { arg: k.into(), e })?,
154 ))
155 }
156 }
157 None => Ok(match i.get(c) {
158 Some(e) => Some(e),
159 None => None,
160 }),
161 }
162 }
163 fn desc2(i: Init<Ctx, T>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
164 [
165 k.into(),
166 format!("Opt<{}>", T::desc()),
167 d.into(),
168 i.to_string(c),
169 ]
170 }
171 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
172 match i.get(c) {
173 Some(i) => Some(i),
174 None => None,
175 }
176 }
177}
178
179impl<'a, 'b, Ctx, T: Parse<'a> + Display> Parse2<'b, 'a, Ctx> for Vec<T> {
180 type I = DisplayVec<T>;
181 fn parse2(
182 i: Init<Ctx, Self::I>,
183 k: &'static str,
184 c: &Ctx,
185 p: &mut ParsedArgs<'a>,
186 ) -> Result<Self, ErrArg> {
187 match p.consume(k) {
188 Some(args) => {
189 let args = args
190 .iter()
191 .map(|a| T::parse(a).map_err(|e| ErrArg::Val { arg: k.into(), e }))
192 .process_results(|i| i.collect_vec())?;
193 if args.is_empty() {
194 Err(ErrArg::OnlyOne { arg: k.into() })?;
195 }
196 Ok(args)
197 }
198 None => Ok(match i.get(c) {
199 Some(e) => e.into(),
200 None => vec![],
201 }),
202 }
203 }
204
205 fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
206 [
207 k.into(),
208 format!("Vec<{}>", T::desc()),
209 d.into(),
210 i.to_string(c),
211 ]
212 }
213 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
214 match i.get(c) {
215 Some(v) => v.0,
216 None => Self::default(),
217 }
218 }
219}
220
221#[derive(Debug)]
222pub struct OptVec<T: Display>(pub Vec<T>);
223impl<T: Display> From<Vec<T>> for OptVec<T> {
224 fn from(v: Vec<T>) -> Self {
225 Self(v)
226 }
227}
228impl<T: Display> From<DisplayVec<T>> for OptVec<T> {
229 fn from(v: DisplayVec<T>) -> Self {
230 Self(v.0)
231 }
232}
233impl<'a, 'b, Ctx, T: Parse<'a>> Parse2<'b, 'a, Ctx> for OptVec<T> {
234 type I = DisplayVec<T>;
235 fn parse2(
236 i: Init<Ctx, Self::I>,
237 k: &'static str,
238 c: &Ctx,
239 p: &mut ParsedArgs<'a>,
240 ) -> Result<Self, ErrArg> {
241 match p.consume(k) {
242 Some(args) => {
243 let args = args
244 .iter()
245 .map(|a| T::parse(a).map_err(|e| ErrArg::Val { arg: k.into(), e }))
246 .process_results(|i| i.collect_vec())?;
247 Ok(args.into())
248 }
249 None => Ok(match i.get(c) {
250 Some(e) => e.into(),
251 None => vec![].into(),
252 }),
253 }
254 }
255
256 fn desc2(i: Init<Ctx, Self::I>, d: &'static str, k: &'static str, c: &Ctx) -> [String; 4] {
257 [
258 k.into(),
259 format!("Vec<{}>", T::desc()),
260 d.into(),
261 i.to_string(c),
262 ]
263 }
264 fn default2(c: &Ctx, i: Init<Ctx, Self::I>) -> Self {
265 Self::from(match i.get(c) {
266 Some(v) => v.0,
267 None => <Vec<T>>::default(),
268 })
269 }
270}
271impl Display for DirExist {
272 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273 write!(f, "{}", self.s)
274 }
275}
276impl Display for FileExist {
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278 write!(f, "{}", self.s)
279 }
280}