1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
use crate;
use FromStr;
/// A trait for parsing a type with `sscanf`.
///
/// There are three ways to implement this trait:
/// - [`#[derive(FromScanf)]`](derive.FromScanf.html) (simple, readable, foolproof) - see [Option 1](#option-1-deriving)
/// - Manually implement [`FromScanfSimple`] (more flexible, more code) - see [Option 2](#option-2-manually-implement-fromscanfsimple)
/// - Manually implement [`FromScanf`] (maximum flexibility and complexity) - see [Option 3](#option-3-manually-implement-fromscanf)
///
/// ## Option 1: Deriving
/// ```
/// # #[derive(Debug, PartialEq)] // additional traits for assert_eq below. Not required for sscanf and thus hidden in the example.
/// #[derive(sscanf::FromScanf)] // The derive macro
/// #[sscanf(format = "{numerator}/{denominator}")] // Format string for the type, using the field names.
/// struct Fraction {
/// numerator: isize,
/// denominator: usize,
/// }
///
/// let parsed = sscanf::sscanf!("-10/3", "{Fraction}").unwrap();
/// assert_eq!(parsed, Fraction { numerator: -10, denominator: 3 });
/// ```
///
/// The derive macro generates the code to parse the type from the format string. It knows the field types and can
/// generate the correct matcher and parser implementation.
///
/// A detailed description of the syntax and options is available in [the derive documentation](derive.FromScanf.html).
///
/// ## Option 2: Manually Implement [`FromScanfSimple`]
/// ```
/// # #[derive(Debug, PartialEq)] // additional traits for assert_eq below. Not required for sscanf and thus hidden in the example.
/// struct Fraction {
/// numerator: isize,
/// denominator: usize,
/// }
///
/// impl sscanf::FromScanfSimple<'_> for Fraction {
/// const REGEX: &'static str = r"[-+]?[0-9]+/[0-9]+"; // (sign) digits '/' digits
///
/// fn from_match(input: &str) -> Option<Self> {
/// let (numerator, denominator) = input.split_once('/').unwrap(); // unwrap is safe here, since the regex guarantees the presence of '/'
/// Some(Self {
/// numerator: numerator.parse().ok()?,
/// denominator: denominator.parse().ok()?,
/// })
/// }
/// }
///
/// let parsed = sscanf::sscanf!("-10/3", "{Fraction}").unwrap();
/// assert_eq!(parsed, Fraction { numerator: -10, denominator: 3 });
/// ```
/// This option gives more control over parsing but requires more code and a regex.
///
/// This option is especially useful for types that already implement [`FromStr`], since the parsing logic can be
/// reused. For example, the above implementation could be simplified to:
///
/// ```
/// # #[derive(Debug, PartialEq)] // additional traits for assert_eq below. Not required for sscanf and thus hidden in the example.
/// struct Fraction {
/// numerator: isize,
/// denominator: usize,
/// }
///
/// impl std::str::FromStr for Fraction {
/// // existing FromStr implementation for Fraction
/// # type Err = &'static str; // simplified error type
/// # fn from_str(input: &str) -> Result<Self, Self::Err> {
/// # let (numerator, denominator) = input.split_once('/').ok_or("Missing '/'")?;
/// # Ok(Self {
/// # numerator: numerator.parse().map_err(|_| "Invalid numerator")?,
/// # denominator: denominator.parse().map_err(|_| "Invalid denominator")?,
/// # })
/// # }
/// }
///
/// impl sscanf::FromScanfSimple<'_> for Fraction {
/// const REGEX: &'static str = r"[-+]?\d+/\d+"; // (sign) digits '/' digits
///
/// fn from_match(input: &str) -> Option<Self> {
/// input.parse().ok() // reuse FromStr implementation
/// }
/// }
///
/// let parsed = sscanf::sscanf!("-10/3", "{Fraction}").unwrap();
/// assert_eq!(parsed, Fraction { numerator: -10, denominator: 3 });
/// ```
///
/// ## Option 3: Manually Implement [`FromScanf`]
/// ```
/// # use sscanf::FromScanf;
/// # #[derive(Debug, PartialEq)] // additional traits for assert_eq below. Not required for sscanf and thus hidden in the example.
/// struct Fraction {
/// numerator: isize,
/// denominator: usize,
/// }
///
/// use sscanf::advanced::*; // for Matcher etc.
/// impl FromScanf<'_> for Fraction {
/// fn get_matcher(options: &FormatOptions) -> Matcher {
/// // matches <isize> '/' <usize>
/// Matcher::Seq(vec![
/// <isize as FromScanf>::get_matcher(options).into(),
/// MatchPart::literal("/"),
/// <usize as FromScanf>::get_matcher(options).into(),
/// ])
/// }
///
/// fn from_match(matches: Match<'_, '_>, options: &FormatOptions) -> Option<Self> {
/// let matches = matches.as_seq(); // our matcher is a sequence, so we can convert to that
/// Some(Self {
/// numerator: matches.parse_field("numerator", 0, options)?,
/// denominator: matches.parse_field("denominator", 2, options)?, // index 1 is the literal '/', so we skip it
/// })
/// }
/// }
///
/// let parsed = sscanf::sscanf!("-10/3", "{Fraction}").unwrap();
/// assert_eq!(parsed, Fraction { numerator: -10, denominator: 3 });
/// ```
/// This option offers fine-grained control over matching and parsing. It is generally faster than
/// [`FromScanfSimple`], since you can access match results directly without reparsing the string. In return, it
/// requires more code and is more complex to implement and maintain.
///
/// Therefore, using the derive macro is recommended to hide this complexity while keeping the same performance.
///
/// #### Lifetime Parameter
/// The lifetime parameter of `FromScanf` and `FromScanfSimple` represents the borrow from the input string given to
/// `sscanf`. If your type borrows from that string (like `&str`), specify the lifetime and match it with the
/// `'input` parameter:
/// ```
/// struct Name<'a, 'b> {
/// first: &'a str,
/// last: &'b str,
/// }
///
/// use sscanf::advanced::*; // for Matcher etc.
/// impl<'input> sscanf::FromScanf<'input> for Name<'input, 'input> {
/// // both parts are given the same input => same lifetime
///
/// fn get_matcher(_: &FormatOptions) -> Matcher {
/// Matcher::Seq(vec![
/// Matcher::from_regex(r"\S+").unwrap().into(), // first name: non-whitespace characters
/// MatchPart::literal(" "),
/// Matcher::from_regex(r"\S+").unwrap().into(), // last name: non-whitespace characters
/// ])
/// }
///
/// fn from_match(matches: Match<'_, 'input>, _: &FormatOptions) -> Option<Self> {
/// let matches = matches.as_seq();
/// Some(Self {
/// first: matches.at(0).text(),
/// last: matches.at(2).text(), // index 1 is the space
/// })
/// }
/// }
///
/// let input = String::from("John Doe");
/// let parsed = sscanf::sscanf!(input, "{Name}").unwrap();
/// assert_eq!(parsed.first, "John");
/// assert_eq!(parsed.last, "Doe");
/// ```
///
/// This enables borrowing from the input string to avoid allocations. The returned value's lifetime is that of the
/// input string:
///
/// ```compile_fail
/// # #[derive(sscanf::FromScanf)]
/// # #[sscanf("{first} {last}")]
/// struct Name<'a, 'b> {
/// first: &'a str,
/// last: &'b str,
/// }
/// // ...same impl setup as above...
///
/// let parsed;
/// {
/// let input = String::from("John Doe"); // locally owned string
/// parsed = sscanf::sscanf!(input, "{Name}").unwrap();
/// // input is dropped here
/// }
/// println!("{} {}", parsed.first, parsed.last); // use after drop
/// ```
///
/// Deriving handles lifetimes automatically by inspecting provided types, though this may not always be perfect.
/// ```
/// #[derive(sscanf::FromScanf)]
/// #[sscanf("{first} {last}")]
/// struct Name<'a, 'b> {
/// first: &'a str,
/// last: &'b str,
/// }
///
/// let input = String::from("John Doe");
/// let parsed = sscanf::sscanf!(input, "{Name}").unwrap();
/// assert_eq!(parsed.first, "John");
/// assert_eq!(parsed.last, "Doe");
/// ```
///
/// A simpler version of [`FromScanf`] for manual implementations.