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
//! # bird-machine //! //! Compile your regular expressions at compile time. //! //! **Almost none of this has actually been implemented yet. Do not use this yet.** //! //! ## Example: find a date //! //! ```rust //! use bird_machine::{bird_machine, Machine}; //! //! #[bird_machine(r"^\d{4}-\d{2}-\d{2}$")] //! struct Date; //! //! assert!(Date::is_match("2014-01-01")); //! ``` //! //! ## Example: iterating over capture groups //! //! ```rust //! use bird_machine::{bird_machine, Machine}; //! //! #[bird_machine(r"(\d{4})-(\d{2})-(\d{2})")] //! struct Date<'a>(&'a str, &'a str, &'a str); //! let input = "2012-03-14, 2013-01-01 and 2014-07-05"; //! let match_info = Date::captures_iter(input) //! .map(|x: Date| format!("Month: {} Day: {} Year: {}", x.1, x.2, x.0)); //! let expected = [ //! "Month: 03 Day: 14 Year: 2012", //! "Month: 01 Day: 01 Year: 2013", //! "Month: 07 Day: 05 Year: 2014", //! ]; //! for (actual, expected) in match_info.zip(expected) { //! assert_eq!(actual, expected); //! } //! ``` //! //! ## Example: replacement with named capture groups //! //! ```rust //! use bird_machine::{bird_machine, Machine}; //! //! #[bird_machine(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})")] //! struct Date<'a> { //! y: &'a str, //! m: &'a str, //! d: &'a str, //! } //! let before = "2012-03-14, 2013-01-01 and 2014-07-05"; //! let after = Date::replace_all(before, "$m/$d/$y"); //! assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014"); //! ``` //! //! ## Example: compile-time rejection of invalid regular expressions //! //! ```rust,compile_fail //! use bird_machine::bird_machine; //! //! #[bird_machine(r"(oops i left this group open")] //! struct Bad; //! ``` use std::borrow::Cow; pub use regex::Match; pub use bird_machine_macros::bird_machine; pub trait Machine<'t>: Sized { const ORIGINAL_REGEX: &'static str; fn captures(text: &'t str) -> Option<Self>; // rust smdh why can this not just return impl Iterator type CaptureIterator: Iterator<Item = Self>; fn captures_iter(text: &'t str) -> Self::CaptureIterator; fn find(text: &'t str) -> Option<Match<'t>>; fn find_at(text: &'t str, start: usize) -> Option<Match<'t>>; // once again i am asking why trait methods can't return impl Iterator type FindIterator: Iterator<Item = Match<'t>>; fn find_iter(text: &'t str) -> Self::FindIterator; fn is_match(text: &'t str) -> bool; fn is_match_at(text: &'t str, start: usize) -> bool; fn replace(text: &'t str, rep: impl Replacer<'t, Self>) -> Cow<'t, str>; fn replace_all(text: &'t str, rep: impl Replacer<'t, Self>) -> Cow<'t, str>; fn replacen(text: &'t str, limit: usize, rep: impl Replacer<'t, Self>) -> Cow<'t, str>; type SplitIterator: Iterator<Item = &'t str>; fn split(text: &'t str) -> Self::SplitIterator; type SplitNIterator: Iterator<Item = &'t str>; fn splitn(text: &'t str, limit: usize) -> Self::SplitNIterator; } pub trait Replacer<'t, M: Machine<'t>> { fn replace_append(&mut self, r#match: &M, dst: &mut String); } impl<'t, M: Machine<'t>, S: AsRef<str>, F: FnMut(&M) -> S> Replacer<'t, M> for F { fn replace_append(&mut self, r#match: &M, dst: &mut String) { let replaced_with = self(r#match); let replaced_with: &str = replaced_with.as_ref(); dst.push_str(replaced_with); } }