ere_macros/lib.rs
1use ere_core;
2use proc_macro::TokenStream;
3
4extern crate proc_macro;
5
6/// This is the primary entrypoint to the `ere` crate.
7/// Checks and compiles a regular expression into a [`Regex<N>`](`ere_core::Regex<N>`).
8///
9/// This compilation happens during build using proc macros,
10/// resulting in rust code equivalent to your regex.
11/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
12///
13/// The generic `const N: usize` will be the number of capture groups present in the regular expression
14/// (including capture group 0 which is the entire matched text).
15/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
16/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
17///
18/// ```
19/// use ere_core::Regex; // usually `ere::Regex`
20/// use ere_macros::compile_regex; // usually `ere::compile_regex`
21///
22/// const MY_REGEX: Regex<2> = compile_regex!("a(b?)c");
23/// ```
24#[proc_macro]
25pub fn compile_regex(stream: TokenStream) -> TokenStream {
26 return ere_core::__compile_regex(stream);
27}
28
29/// Checks and compiles a regular expression into a into a [`ere_core::Regex<N>`] with the [`ere_core::pike_vm`] engine.
30/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
31///
32/// This compilation happens during build using proc macros,
33/// resulting in rust code equivalent to your regex.
34/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
35///
36/// The generic `const N: usize` will be the number of capture groups present in the regular expression
37/// (including capture group 0 which is the entire matched text).
38/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
39/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
40///
41/// ```
42/// use ere_core::Regex;
43/// use ere_macros::compile_regex_pikevm;
44///
45/// const MY_REGEX: Regex<2> = compile_regex_pikevm!("a(b?)c");
46/// ```
47#[proc_macro]
48pub fn compile_regex_pikevm(stream: TokenStream) -> TokenStream {
49 return ere_core::__compile_regex_engine_pike_vm(stream);
50}
51
52/// Checks and compiles a regular expression into a into a [`ere_core::Regex<N>`] with the [`ere_core::pike_vm_u8`] engine.
53/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
54///
55/// This compilation happens during build using proc macros,
56/// resulting in rust code equivalent to your regex.
57/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
58///
59/// The generic `const N: usize` will be the number of capture groups present in the regular expression
60/// (including capture group 0 which is the entire matched text).
61/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
62/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
63///
64/// ```
65/// use ere_core::Regex;
66/// use ere_macros::compile_regex_u8pikevm;
67///
68/// const MY_REGEX: Regex<2> = compile_regex_u8pikevm!("a(b?)c");
69/// ```
70#[proc_macro]
71pub fn compile_regex_u8pikevm(stream: TokenStream) -> TokenStream {
72 return ere_core::__compile_regex_engine_pike_vm_u8(stream);
73}
74
75/// Checks and compiles a regular expression into a [`ere_core::Regex<N>`] with the [`ere_core::one_pass_u8`] engine.
76/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
77///
78/// This compilation happens during build using proc macros,
79/// resulting in rust code equivalent to your regex.
80/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
81///
82/// The generic `const N: usize` will be the number of capture groups present in the regular expression
83/// (including capture group 0 which is the entire matched text).
84/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
85/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
86///
87/// ```
88/// use ere_core::Regex;
89/// use ere_macros::compile_regex_u8onepass;
90///
91/// const MY_REGEX: Regex<2> = compile_regex_u8onepass!("^a(b?)c$");
92/// ```
93///
94/// ---
95///
96/// Note that this engine does not support all valid regular expressions,
97/// and will raise a compile error if necessary.
98/// For example, unanchored regexes are generally not one-pass.
99///
100#[proc_macro]
101pub fn compile_regex_u8onepass(stream: TokenStream) -> TokenStream {
102 return ere_core::__compile_regex_engine_one_pass_u8(stream);
103}
104
105/// Checks and compiles a regular expression into a [`ere_core::Regex<N>`] with the [`ere_core::fixed_offset`] engine.
106/// Unless you specifically want this engine, you might want to use [`compile_regex!`] instead.
107///
108/// This compilation happens during build using proc macros,
109/// resulting in rust code equivalent to your regex.
110/// This code can then by further optimized by rustc/llvm when compiled directly into the binary.
111///
112/// The generic `const N: usize` will be the number of capture groups present in the regular expression
113/// (including capture group 0 which is the entire matched text).
114/// You will need to properly specify this in the generics for the regex (default if unspecified is 1).
115/// When using [`Regex<N>::exec`](`ere_core::Regex<N>::exec`), this is the length of the captures returned.
116///
117/// ```
118/// use ere_core::Regex;
119/// use ere_macros::compile_regex_fixed_offset;
120///
121/// const MY_REGEX: Regex<2> = compile_regex_fixed_offset!("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$");
122/// ```
123///
124/// ---
125///
126/// Note that this engine does not support all valid regular expressions,
127/// and will raise a compile error if necessary..
128///
129#[proc_macro]
130pub fn compile_regex_fixed_offset(stream: TokenStream) -> TokenStream {
131 return ere_core::__compile_regex_engine_fixed_offset(stream);
132}
133
134/// EXPERIMENTAL: this attribute provides an alternate syntax with finer control for creating regexes.
135///
136/// Compared with [`compile_regex!`], this allows the type system to know which capture groups
137/// should be optional and which should not.
138///
139/// For example:
140///
141/// ```
142/// use ere_macros::regex;
143///
144/// #[derive(Debug, PartialEq, Eq)]
145/// #[regex(r"^#?([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})?$")]
146/// pub struct HexColor<'a>(
147/// pub &'a str,
148/// pub &'a str,
149/// pub &'a str,
150/// pub &'a str,
151/// pub Option<&'a str>,
152/// );
153///
154/// assert!(HexColor::test("#1F1F1F"));
155/// assert!(HexColor::test("#1F1F1F80"));
156/// assert!(HexColor::test("20202020"));
157///
158/// assert_eq!(
159/// HexColor::exec("#112233"),
160/// Some(HexColor(
161/// "#112233",
162/// "11",
163/// "22",
164/// "33",
165/// None,
166/// )),
167/// );
168/// assert_eq!(
169/// HexColor::exec("#11223344"),
170/// Some(HexColor(
171/// "#11223344",
172/// "11",
173/// "22",
174/// "33",
175/// Some("44"),
176/// )),
177/// );
178/// ```
179///
180/// ---
181///
182/// Note that it is required to specify the fields with the proper type
183/// (i.e. `&'a str` or `Option<&'a str>` depending on the capture group)
184/// and the lifetime should be the first generic argument on the struct.
185///
186/// The field for the 0th capture group should never be an `Option` since if there is a match,
187/// it will always contain the entire match (and otherwise `exec` returns `None`).
188#[cfg(feature = "unstable-attr-regex")]
189#[proc_macro_attribute]
190pub fn regex(attr: TokenStream, input: TokenStream) -> TokenStream {
191 return ere_core::__compile_regex_attr(attr, input);
192}