1use crate::arg::{ArgType, extract_subspan};
2use crate::fields::*;
3use crate::parse::parse_scalar;
4use crate::results::*;
5use alloc::borrow::Cow;
6use core::fmt;
7use facet_core::Facet;
8use facet_deserialize::{
9 DeserError, DeserErrorKind, Expectation, Format, NextData, NextResult, Outcome, Raw, Scalar,
10 Span, Spanned,
11};
12
13pub struct Cli;
15
16impl fmt::Display for Cli {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 write!(f, "Cli")
19 }
20}
21
22pub fn from_slice<'input, 'facet, 'shape, T: Facet<'facet>>(
24 args: &'input [&'input str],
25) -> Result<T, DeserError<'input, 'shape>>
26where
27 'input: 'facet + 'shape,
28{
29 facet_deserialize::deserialize(args, Cli)
30}
31
32impl Format for Cli {
33 type Input<'input> = [&'input str];
34 type SpanType = Raw;
35
36 fn source(&self) -> &'static str {
37 "args"
38 }
39
40 fn next<'input, 'facet, 'shape>(
41 &mut self,
42 nd: NextData<'input, 'facet, 'shape, Self::SpanType, Self::Input<'input>>,
43 expectation: Expectation,
44 ) -> NextResult<
45 'input,
46 'facet,
47 'shape,
48 Spanned<Outcome<'input>, Self::SpanType>,
49 Spanned<DeserErrorKind<'shape>, Self::SpanType>,
50 Self::SpanType,
51 Self::Input<'input>,
52 >
53 where
54 'shape: 'input,
55 {
56 let arg_idx = nd.start();
57 let shape = nd.wip.shape();
58 let args = nd.input();
59 let subspans = nd.substack().get();
60 let has_subspans = !subspans.is_empty();
61
62 let stay_put = Span::new(arg_idx, 0);
63 let step_forth = Span::new(arg_idx, 1);
64
65 let span = match expectation {
66 Expectation::Value => stay_put,
67 Expectation::ObjectKeyOrObjectClose
68 | Expectation::ObjectVal
69 | Expectation::ListItemOrListClose => step_forth,
70 };
71
72 let result = match expectation {
73 Expectation::Value => {
75 wrap_outcome_result(validate_struct_type(shape), Outcome::ObjectStarted, span)
77 }
78
79 Expectation::ObjectKeyOrObjectClose => {
81 if arg_idx < args.len() {
83 let arg = args[arg_idx];
84
85 if arg.starts_with("-") && arg.contains('=') && !has_subspans {
87 if let Some(key_value_subspans) = create_key_value_subspans(arg) {
89 return (nd, wrap_resegmented_result(key_value_subspans, stay_put));
90 }
91 }
92
93 let effective_arg = if has_subspans {
95 extract_subspan(&subspans[0], arg)
96 } else {
97 arg
98 };
99
100 match ArgType::parse(effective_arg) {
102 ArgType::LongFlag(key) => {
103 wrap_string_result(
105 validate_field(&key, shape, &nd.wip).map(|_| key),
106 if has_subspans { stay_put } else { span },
107 )
108 }
109 ArgType::ShortFlag(key) => {
110 wrap_field_result(
112 find_field_by_short_flag(key, shape),
113 if has_subspans { stay_put } else { span },
114 )
115 }
116 ArgType::Positional => {
117 wrap_field_result(find_positional_field(shape, &nd.wip), stay_put)
119 }
120 ArgType::None => {
121 let err = create_unknown_field_error("empty argument", shape);
123 Err(Spanned { node: err, span })
124 }
125 }
126 } else {
127 handle_unset_bool_field_error(find_unset_bool_field(shape, &nd.wip), span)
129 }
130 }
131
132 Expectation::ObjectVal => {
134 if shape.is_type::<bool>() {
136 let has_arg = arg_idx < args.len();
138 wrap_result(handle_bool_value(has_arg), Outcome::Scalar, stay_put)
139 } else {
140 let result = if has_subspans && arg_idx < args.len() {
142 let arg = args[arg_idx];
143 let subspan = &subspans[1];
144 let arg_type: ArgType = (subspan, arg).into();
145
146 match arg_type {
148 ArgType::ShortFlag(_) | ArgType::LongFlag(_) => {
149 None
151 }
152 _ => {
153 let part = extract_subspan(subspan, arg);
155 Some(Ok(parse_scalar(part, span)))
156 }
157 }
158 } else {
159 None
160 };
161
162 result.unwrap_or_else(|| {
164 match validate_value_available(arg_idx, args) {
166 Ok(arg) => Ok(parse_scalar(arg, span)),
167 Err(err) => Err(Spanned {
168 node: err,
169 span: Span::new(arg_idx.saturating_sub(1), 0),
170 }),
171 }
172 })
173 }
174 }
175
176 Expectation::ListItemOrListClose => {
178 if is_list_ended(arg_idx, args) {
180 Ok(Spanned {
182 node: Outcome::ListEnded,
183 span,
184 })
185 } else {
186 Ok(Spanned {
188 node: Outcome::Scalar(Scalar::String(Cow::Borrowed(args[arg_idx]))),
189 span: step_forth,
190 })
191 }
192 }
193 };
194
195 (nd, result)
196 }
197
198 fn skip<'input, 'facet, 'shape>(
199 &mut self,
200 nd: NextData<'input, 'facet, 'shape, Self::SpanType, Self::Input<'input>>,
201 ) -> NextResult<
202 'input,
203 'facet,
204 'shape,
205 Span<Self::SpanType>,
206 Spanned<DeserErrorKind<'shape>, Self::SpanType>,
207 Self::SpanType,
208 Self::Input<'input>,
209 >
210 where
211 'shape: 'input,
212 {
213 let arg_idx = nd.start();
214 let args = nd.input();
215 let span = Span::new(arg_idx, 1);
216
217 let result = if arg_idx < args.len() {
218 Ok(span)
220 } else {
221 Err(Spanned {
223 node: DeserErrorKind::UnexpectedEof {
224 wanted: "argument to skip",
225 },
226 span,
227 })
228 };
229
230 (nd, result)
231 }
232}