ct_regex/
lib.rs

1//! A crate for creating types that match regular expressions at compile time.
2//! [`Regex`]-implementing types can be created with the [`regex!`] macro.
3//!
4//! This crate was heavily inspired by [`ctreg`](https://docs.rs/ctreg/latest/ctreg/), which
5//! provides named, infallible capture groups and syntax error checking at compile time.
6//!
7//! I'm yet to do a complexity analysis on this crate, but it should generally have time complexity
8//! `O(n*m)` where `n` and `m` are the length of the pattern and haystack, the same as most regex
9//! crates.
10//!
11//! # Approach
12//!
13//! How does this crate differ from the many other regex crates on crates.io?
14//!
15//! The answer is in the name: it creates types that match regular expressions at _compile time_, as
16//! opposed to runtime like most other implementations.
17//!
18//! 1. As with most crates, this one starts by parsing the provided expressions using the
19//! [`regex_syntax`](https://docs.rs/regex-syntax/latest/regex_syntax/) crate, producing an _abstract
20//! syntax tree_ before translating and optimising into a _high-level intermedite representation_
21//! (HIR).
22//!
23//! 2. Rather than using [NFAs](https://en.wikipedia.org/wiki/Thompson%27s_construction) or DFAs,
24//! the macro converts the HIR into a Rust type expression, made of
25//! [`Matcher`](ct_regex_internal::matcher::Matcher) components that describe the various types of
26//! matching / capturing a regular expression. An _simple_ example of this generated type expression
27//! can be seen at [`demo::Email::Pattern`](demo/struct.Email.html#associatedtype.Pattern-1).
28//!
29//! 3. The macro finishes and the binary is compiled normally, using a collection of associated
30//! functions on each `Matcher` to perform the relvant matching / capturing. In short, matching or
31//! capturing at runtime boils down to a series of function calls, which the Rust compile can
32//! optimise as it sees fit.
33//!
34//! # When not to use this crate
35//!
36//! For runtime regular expressions (_gasp_). Seriously though, most of the work done by this crate
37//! occurs when building the binary, so it isn't possible to create expressions on the fly. See one
38//! of the other crates listed above if this is something you want.
39//!
40//! Some complex functionality isn't implement yet, including complex look-arounds etc. An error
41//! will occur at **compile-time** if you try to use an unimplemented feature.
42
43#![feature(doc_cfg)]
44
45// TODO: Double check time complexity, write some benchmarks.
46
47// Enable the crate to reference itself by name (needed for macro expansion)
48extern crate self as ct_regex;
49
50pub use ct_regex_internal::expr::{AnonRegex, Regex};
51pub use ct_regex_macro::regex;
52
53#[cfg(any(doc, feature = "demo"))]
54#[doc(cfg(feature = "demo"))]
55pub mod demo;
56
57pub mod haystack;
58
59#[doc(hidden)]
60pub mod internal {
61    pub use ct_regex_internal::*;
62}
63
64#[cfg(test)]
65mod tests;