prse_derive/
lib.rs

1#![warn(missing_docs)]
2//! A helper crate for prse, the small string parsing library.
3
4extern crate proc_macro2;
5#[macro_use]
6extern crate quote;
7#[macro_use]
8extern crate syn;
9
10use derive::Derive;
11use invocation::ParseInvocation;
12use proc_macro::TokenStream;
13use quote::ToTokens;
14
15mod derive;
16mod expand_derive;
17mod instructions;
18mod invocation;
19mod var;
20
21/// The `parse` macro allows you to parse a string into any type that implements [`Parse`](trait.Parse.html).
22/// (Which can be derived with the [`Parse`](derive.Parse.html) macro)
23///
24/// ```ignore
25/// let input = "5 + -2 = 3";
26///
27/// let total: i32;
28/// let (lhs, rhs): (i32, i32) = parse!(input, "{} + {} = {total}");
29///
30///
31/// assert_eq!(lhs + rhs, total);
32///
33/// // You can also specify the variable's position in the tuple.
34///
35/// let (rhs, lhs): (u32, u32) = parse!("10 / 2", "{1} / {0}");
36///
37/// assert_eq!(lhs / rhs, 5);
38/// ```
39///
40/// # Repetition
41///
42/// You can parse multiple parts of a string using one of the following methods:
43///
44/// ## Array
45///
46/// You can parse a string into an array of parsed elements using the following syntax `{<var>:<sep>:<count>}`.
47///
48/// ```ignore
49/// let input = "My farm contains exactly 3 animals: Beatrice, Betsy, Callum";
50///
51/// // var = nothing, sep = ", " and count = 3
52/// let array: [&str; 3] = parse!(input, "My farm contains exactly 3 animals: {:, :3}");
53///
54/// assert_eq!(array, ["Beatrice", "Betsy", "Callum"]);
55/// ```
56/// ## Vec
57///
58/// You can parse a string into a Vec of parsed elements using the following syntax `{<var>:<sep>:}`.
59/// This way of parsing is only available if the alloc feature has been enabled.
60///
61/// ```ignore
62/// let input = "My farm contains some amount of booleans: true || false || true || false";
63/// let many: Vec<bool>;
64///
65/// // var = many and sep = " || "
66/// parse!(input, "My farm contains some amount of booleans: {many: || :}");
67///
68/// assert_eq!(many, vec![true, false, true, false]);
69/// ```
70/// ## Iterator
71///
72/// Alternatively if you are unable to allocate anything then you can use a lazy iterator
73/// by using the following syntax `{<var>:<sep>:0}`.
74///
75/// One important note is that since the iterator is evaluated lazily it will always return an iterator of [`Results`](Result).
76///
77/// The returned iterator will either be [`ParseIter`](struct.ParseIter.html) or [`ParseChars`](struct.ParseChars.html) if the separator is empty.  
78///
79///
80/// ```ignore
81/// let input = "My farm has this many animals: [5,23,42,1,3,5]";
82///
83/// // var = nothing and sep = ","
84/// let animal_count: u32 = parse!(input, "My farm has this many animals: [{:,:0}]")
85///     .flat_map(|c: Result<u32, _>| c.ok())
86///     .sum();
87///
88/// assert_eq!(animal_count, 79);
89/// ```
90///
91///
92/// ## Modifiers
93///
94/// All three multi-parsers (Array, Vec and Iterator) allow `{<var>:<sep>:!<kind>}` syntax to skip multiple separators, for example
95/// ```ignore
96/// assert_eq!([1, 2, 3], parse!("1-2---3", "{:-:!3}"));
97/// ```
98/// ## Empty separators
99///
100/// If the separator is an empty string slice (e.g. `{::}`) then the multi-parsers will iterate over every [char].
101/// ```ignore
102/// assert_eq!([3, 2, 1], parse!("321", "{::3}"))
103/// ```
104/// # Syntax
105///
106/// The [`parse!`] macro uses a literal with `{}` brackets to denote where it should
107/// try to parse into a type. The macro must fully consume the string as it will otherwise
108/// return an error. If this is not what you want you can create a dummy capture variable
109/// that captures the rest of the string.
110///
111/// ```ignore
112/// let input = "Hello world! Today is a great day!";
113/// let world: &str;
114///
115/// // We only care about world so capture everything else as a string to prevent an error.
116/// let _capture: &str = parse!(input, "Hello {world}!{}")
117///
118/// assert_eq!(world, "world");
119/// ```
120///
121///
122/// ## Escaping
123///
124/// The `{` and `}` brackets can be escaped by doubling them up. This leads to the following syntax:
125///
126/// ```ignore
127/// let input = "Stuff in {} is really important: {42}";
128/// let num: u128;
129///
130/// parse!(input, "Stuff in {{}} is really important: {{{num}}}");
131///
132/// assert_eq!(num, 42);
133/// ```
134#[proc_macro]
135pub fn parse(input: TokenStream) -> TokenStream {
136    let input = parse_macro_input!(input as ParseInvocation);
137    input.to_token_stream().into()
138}
139
140/// Returns a [`Result`](https://doc.rust-lang.org/stable/std/result/enum.Result.html) instead of unwrapping like [`parse!`]. The [`Result`](https://doc.rust-lang.org/stable/std/result/enum.Result.html) has
141/// [`ParseError`](enum.ParseError.html) as the error type.
142///
143/// For more information please look at [`parse!`].
144/// ```ignore
145/// let input = "cd C:\\windows\\system32";
146/// let path: Result<PathBuf, _> = try_parse!(input, "cd {}");
147///
148/// assert_eq!(path.unwrap(), PathBuf::from("C:\\windows\\system32"));
149/// ```
150#[proc_macro]
151pub fn try_parse(input: TokenStream) -> TokenStream {
152    let mut input = parse_macro_input!(input as ParseInvocation);
153    input.try_parse = true;
154    input.to_token_stream().into()
155}
156
157/// Automatically implements the [`Parse`](trait.Parse.html) trait using one of two methods.
158///
159/// You can define how each field should be parsed using the `prse` attribute.
160/// The prse attribute uses the same syntax as [`parse!`] and even supports Vec, Iterator and Array repetition.
161///
162///```ignore
163/// use prse::{parse, Parse};
164///
165/// #[derive(Debug, Parse)]
166/// #[prse = "({x}, {y})"]
167/// struct Position {
168///     x: i32,
169///     y: i32,
170/// }
171///
172/// let pos: Position = parse!("This is a position: (1, 2)", "This is a position: {}");
173/// assert_eq!(pos.x, 1);
174/// assert_eq!(pos.y, 2);
175///```
176///
177/// This can also be done on enums.
178///
179///```ignore
180/// use prse::{parse, Parse};
181///
182/// #[derive(Debug, Parse, Eq, PartialEq)]
183/// enum Position {
184///     #[prse = "({x}, {y})"]
185///     Pos { x: i32, y: i32 },
186///     #[prse = "({})"]
187///     SinglePos(i32),
188///     #[prse = "()"]
189///     #[prse = ""]
190///     NoPos,
191/// }
192///
193/// // the first prse attribute to match is used.
194/// let pos0: Position = parse!("This is a position: (1, 2)", "This is a position: {}");
195/// let pos1: Position = parse!("This is a position: (3)", "This is a position: {}");
196/// let pos2: Position = parse!("This is a position: ()", "This is a position: {}");
197/// let pos3: Position = parse!("This is a position: ", "This is a position: {}");
198///
199/// assert_eq!(pos0, Position::Pos { x: 1, y: 2 });
200/// assert_eq!(pos1, Position::SinglePos(3));
201/// assert_eq!(pos2, Position::NoPos);
202/// assert_eq!(pos3, Position::NoPos);
203///```
204/// If no prse attributes are found, it will use your [`FromStr`](core::str::FromStr) implementation.
205/// ```ignore
206/// use prse::{parse, Parse};
207///
208/// #[derive(Debug, Parse)]
209/// struct Position {
210///     x: i32,
211///     y: i32,
212/// }
213///
214/// impl std::str::FromStr for Position {
215///     type Err = ();
216///
217///     fn from_str(mut s: &str) -> Result<Self, Self::Err> {
218///         s = s.strip_prefix('(').ok_or(())?;
219///         s = s.strip_suffix(')').ok_or(())?;
220///         let (x, y) = s.split_once(',').ok_or(())?;
221///         Ok(Position {
222///             x: x.parse().map_err(|_| ())?,
223///             y: y.trim().parse().map_err(|_| ())?,
224///         })
225///     }
226/// }
227///
228/// let pos: Position = parse!("This is a position: (1, 2)", "This is a position: {}");
229/// assert_eq!(pos.x, 1);
230/// assert_eq!(pos.y, 2);
231/// ```
232#[proc_macro_derive(Parse, attributes(prse))]
233pub fn derive_parse(input: TokenStream) -> TokenStream {
234    let input = parse_macro_input!(input as Derive);
235    input.into_token_stream().into()
236}