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
//! Macro re-exports to keep documentation separate from the crate root.
use crateParser;
/// Parses a string using a format string, similar to C's `sscanf`.
///
/// ## Signature
/// ```ignore
/// sscanf!(input: impl Deref<Target=str>, format: <literal>, Type...) -> Option<(Type...)>
/// ```
///
/// ## Parameters
/// * `input`: The string to parse. Can be anything that auto-derefs to `str` (e.g. `&str`, `String`, `Cow<str>`, etc.).
/// See the examples below. Note that `sscanf` does not take ownership of the input.\
/// More formally, `sscanf` adds a `&` before the input and then passes it to [`Parser::parse`](crate::Parser::parse),
/// so the input must be something that rust can coerce to `&str`.
/// * `format`: A literal string. No `const` or `static` allowed, just like with [`format!()`](std::format).
/// * `Type...`: Any types that are not written into the format string. See [Custom Types](index.html#custom-types)
/// for details.
///
/// ## Return Value
/// Returns `Some(tuple)` containing the parsed types, or `None` if matching or parsing fails.
///
/// ## Details
/// The format string must be a string literal, because it is parsed by the procedural macro at compile time to ensure
/// all types and placeholders match. This cannot be done if the format is stored in a variable or even a `const &str`
/// elsewhere.
///
/// Placeholders in the format string are `{}`. Any `{` or `}` that should be literal must be escaped as `{{` and `}}`.
/// For every placeholder there must be a type name inside the `{}`, or exactly one type in the parameters after the
/// format string. Types can be referenced by indices like `{0}`, similar to [`format!()`](std::format).
///
/// Any additional formatting options are placed after a `:`. For a list of options, see the
/// [crate root documentation](index.html#format-options).
///
/// ## Examples
/// Examples of accepted input types:
/// ```
/// # use sscanf::sscanf; use std::{borrow::Cow, rc::Rc, boxed::Box};
/// let input = "5"; // &str
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
///
/// let input = String::from("5"); // String
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
///
/// let input = &input; // &String
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
/// assert_eq!(sscanf!(input.as_str(), "{usize}").unwrap(), 5);
///
/// let input: Box<str> = String::from("5").into_boxed_str();
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
///
/// let input: Cow<str> = Cow::Borrowed("5");
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
///
/// let input: Rc<str> = Rc::from(String::from("5"));
/// assert_eq!(sscanf!(input, "{usize}").unwrap(), 5);
///
/// // and many more
/// ```
///
/// ```compile_fail
/// // temporary value: does not work
/// # use sscanf::sscanf;
/// sscanf!(String::from("5"), "{usize}");
/// ```
///
/// More examples are available in the crate root documentation.
pub use sscanf;
/// Same as [`sscanf`], but allows using regex in the format string.
///
/// Signature is the same as [`sscanf`].
///
/// Parameters are the same as [`sscanf`], but any non-placeholder parts of the format string are treated as regex.
///
/// Note that the `{{` and `}}` escaping for literal `{` and `}` is still required. So if you want to have a
/// counted repetition like `[0-9]{4}` as part of the regex, you have to write it as `[0-9]{{4}}`.
///
/// The pattern is automatically anchored: `^` at the start and `$` at the end.
///
/// ## Examples
/// ```
/// use sscanf::sscanf_with_regex;
/// let input = "5.0SOME_RANDOM_TEXT3";
/// let output = sscanf_with_regex!(input, "{f32}.*?{usize}"); // .*? matches anything
/// assert_eq!(output.unwrap(), (5.0, 3));
/// ```
///
/// The basic [`sscanf`] escapes `.`, `*`, and `?` and matches literal characters:
/// ```
/// use sscanf::sscanf;
/// let input = "5.0SOME_RANDOM_TEXT3";
/// let output = sscanf!(input, "{f32}.*{usize}");
/// assert!(output.is_none()); // does not match
///
/// let input2 = "5.0[a-z]3";
/// let output2 = sscanf!(input2, "{f32}[a-z]{usize}"); // regular sscanf is unaffected by special characters
/// assert_eq!(output2.unwrap(), (5.0, 3));
/// ```
pub use sscanf_with_regex;
/// Converts a format string and types into a [`Parser`] that can be reused to parse multiple inputs.
///
/// ## Signature
/// ```ignore
/// sscanf_parser!(format: <literal>, Type...) -> Parser<(Type...)>
/// ```
///
/// ## Parameters
/// * `format`: A literal string. No `const` or `static` allowed, just like with [`format!()`](std::format).
/// * `Type...`: Any types that are not written into the format string. See [Custom Types](index.html#custom-types)
/// for details.
///
/// ## Return Value
/// Returns a [`Parser`] over the parsed tuple. Use the [`parse`](crate::Parser::parse) method to parse inputs.
///
/// ## Details
/// Code like
/// ```ignore
/// sscanf!(input, "<format>", Type...)
/// ```
/// is identical to
/// ```ignore
/// sscanf_parser!("<format>", Type...).parse(input)
/// ```
///
/// Parsers can be reused across inputs. Creating a parser is semi-costly, so reusing it avoids overhead in loops with
/// the same format and types.
///
/// For types that borrow from the input string, lifetimes restrict how long a parser may live. See [`Parser`]
/// documentation for details.
///
/// ## Examples
/// ```
/// use sscanf::{sscanf_parser, Parser};
/// let mut parser: Parser<(&str, i32)> = sscanf_parser!("{&str} {i32}");
///
/// let multiline_input = "Hello 1\nWorld 2\nRust 3";
/// let parsed = multiline_input
/// .lines()
/// .filter_map(|line| parser.parse(line))
/// .collect::<Vec<_>>();
///
/// assert_eq!(parsed, vec![("Hello", 1), ("World", 2), ("Rust", 3)]);
/// ```
pub use sscanf_parser;
/// Same as [`sscanf_parser`], but allows using regex in the format string.
///
/// Signature and parameters are the same as [`sscanf_parser`]; format string handling matches
/// [`sscanf_with_regex`].
///
/// ## Examples
/// ```
/// use sscanf::sscanf_parser_with_regex;
/// let mut parser = sscanf_parser_with_regex!(r"{&str}\s+{i32}");
///
/// let aligned_table = r#"Name Integer
/// Hello 1
/// World 2
/// of 3456789
/// Rust 10"#;
///
/// let parsed = aligned_table
/// .lines()
/// .skip(1) // skip header line
/// .map(|line| parser.parse(line).unwrap())
/// .collect::<Vec<_>>();
///
/// assert_eq!(parsed, vec![("Hello", 1), ("World", 2), ("of", 3456789), ("Rust", 10)]);
/// ```
pub use sscanf_parser_with_regex;
/// Derive macro for [`FromScanf`](crate::FromScanf).
///
/// ## For structs
/// ```ignore
/// #[derive(sscanf::FromScanf)]
/// #[sscanf(format = "<format>")] // format string; must contain placeholders for all
/// struct MyStruct { // non-default fields: {<field>}, {<field_2>}, {<field_with_conversion>}
///
/// <field>: <type>, // requires <type> to implement FromScanf
///
/// <field_2>: <type_2>, // requires `<type_2>: FromScanf`
///
/// // ...
///
/// // possible attributes on fields:
///
/// #[sscanf(default)]
/// <field_with_default>: <type>, // requires `<type>: Default`, but doesn't need FromScanf
///
/// #[sscanf(default = <expression>)] // accepts any expression that returns <type>
/// <field_with_custom_default>: <type>, // no traits required.
///
/// #[sscanf(map = |input: <matched_type>| { <conversion from <matched_type> to <actual_type>> })]
/// <field_with_conversion>: <actual_type>, // requires `<matched_type>: FromScanf`
/// }
///
/// // tuple structs have the same capabilities, just without field names:
/// #[derive(sscanf::FromScanf)]
/// #[sscanf(format = "<format>")] // format string references fields by index: {0}, ...
/// struct MyTupleStruct(<type>, #[sscanf(default)] <type>, ...);
/// ```
///
/// ### Attributes
///
/// #### On the struct
///
/// - `format`: The format string to parse the struct from. Similar to the format string for [`sscanf`], but with field
/// names or indices instead of types. For a struct with fields `a`, `b`, and `c`, a format could be
/// `"{a} {b:/.*?/} {c}"`. All non-`default` fields must appear exactly once. Names or indices can be omitted when
/// fields are in the same order as `{}` placeholders, so the above can also be `"{} {:/.*?/} {}"`.
/// - `format_regex`: Same as `format`, but allows using regex in the format string. See [`sscanf_with_regex`] for
/// details.
/// - `transparent`: If the struct has exactly one field, the struct will be constructed from the field directly. This
/// is useful for newtype structs, where the struct is just a wrapper around another type. The field has to implement
/// [`FromScanf`](crate::FromScanf).
///
/// Only one of the above attributes can be used on a struct at a time. The `format = ` part can be omitted,
/// so `#[sscanf("<format>")]` is also valid.
///
/// #### On the fields
/// - `default` or `default = <expression>`: Sets the field from a default value rather than the input string.
/// `#[sscanf(default)]` uses [`Default::default()`](Default). If the type doesn't implement [`Default`], provide an
/// expression to compute the value. The expression can be any code, including function calls or `{ <code> }` blocks,
/// as long as it produces the field type.
/// - `map = |<param>: <type>| <conversion>`: Matches a different type and maps it to the field type. The closure's
/// parameter type must be specified, since it is needed for matching.
/// - `filter_map = |<param>: <type>| <conversion>`: Like `map`, but returns an [`Option`]. If it returns [`None`],
/// parsing fails.
/// - `from = <type>`: Matches a different type that implements [`FromScanf`] and converts it using [`From`].
/// - `try_from = <type>`: Like `from`, but the conversion can fail. If it does, parsing fails.
///
/// ## For enums
/// ```ignore
/// #[derive(sscanf::FromScanf)]
/// enum MyEnum {
/// #[sscanf(format = "<format>")] // has to contain `{<field>}` and any other fields
/// Variant1 {
/// <field>: <type>, // requires `<type>: FromScanf`
///
/// #[sscanf(default)]
/// <field_with_default>: <type2>, // requires `<type2>: Default`
///
/// // ... (same as for structs)
/// },
///
/// #[sscanf("<format>")] // the `format = ` part can be omitted
/// Variant2(<type>, #[sscanf(default)] <type2>),
///
/// #[sscanf("<format>")] // variant has no fields => no placeholders in format string
/// Variant3,
///
/// Variant4, // this variant won't be constructed by sscanf
/// }
/// ```
/// An enum takes multiple format strings - one per variant. The value returned from `sscanf` is constructed from the
/// variant that matches the input. If multiple variants match, the first one in the enum definition is used. If no
/// variant matches, parsing fails.
///
/// ### Attributes
///
/// #### On the enum
/// - `autogen = "<case>"` or `autogenerate = "<case>"`: Automatically create format strings for all variants
/// based on the variant names. This only works for variants without fields. You can override the format by adding
/// a format attribute on the variant. The `case` parameter can be one of:
/// - `"CaseSensitive"`: The variant name is used as-is. Default if no `case` parameter is specified.
/// - `"CaseInsensitive"`: Same as `"CaseSensitive"`, but case is ignored.
/// - `"lower case"`: Lower case with spaces between words.
/// - `"UPPER CASE"`: Upper case with spaces between words.
/// - `"lowercase"`: Lower case, but without spaces.
/// - `"UPPERCASE"`: Upper case, but without spaces.
/// - `"PascalCase"`
/// - `"camelCase"`
/// - `"snake_case"`
/// - `"SCREAMING_SNAKE_CASE"`
/// - `"kebab-case"`
/// - `"SCREAMING-KEBAB-CASE"`
///
/// #### On the variants
///
/// Same as for structs. If neither a format string nor `transparent` is specified, the variant won't be constructed
/// by `sscanf`. With `autogen`, a format string is generated automatically; to prevent this, add `skip` to the variant.
/// `skip` has no effect without `autogen`.
///
pub use FromScanf;