1use std::error::Error;
2
3pub trait RegexParse: Sized {
4 fn parse(text: &str) -> Result<Self, Box<dyn Error>>;
5}
6
7macro_rules! impl_regex {
8 ($($ty:ty)+) => {
9 $(
10 impl RegexParse for $ty {
11 fn parse(text: &str) -> Result<Self, Box<dyn Error>> {
12 Ok(text.trim().parse::<$ty>()?)
13 }
14 }
15 )+
16 }
17}
18
19impl_regex! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
20impl_regex! { f32 f64 bool String }
21
22impl<T: RegexParse> RegexParse for Vec<T> {
23 fn parse(text: &str) -> Result<Self, Box<dyn Error>> {
24 let mut result = vec![];
25 for item in text.split(',') {
26 result.push(T::parse(item)?);
27 }
28 Ok(result)
29 }
30}
31
32#[cfg(test)]
33mod test {
34 use std::error::Error;
35
36 use regex::Regex;
37
38 use crate::RegexParse;
39
40 use regex_parse_proc_macro::regex;
41
42 fn test(string: &str) -> Result<Vec<i32>, Box<dyn Error>> {
43 let mut result = vec![];
44
45 for item in string.split('.') {
46 result.push(i32::parse(item)?);
47 }
48
49 Ok(result)
50 }
51
52 #[derive(Default, Debug, PartialEq)]
53 #[regex(regex = r"Game(?<id>[^:]+):(?<winning_nums>[^;]+);(?<nums>.*)")]
54 pub struct Game {
55 pub id: i32,
56 #[regex(method = "test")]
57 pub winning_nums: Vec<i32>,
58 pub nums: Vec<i32>,
59 }
60
61 #[test]
62 pub fn test_parse_game() {
63 let string = "Game 1: 1. 2. 3. 4; 1, 2, 3".to_string();
64
65 let game = Game::parse(&string);
66
67 assert_eq!(
68 game.unwrap(),
69 Game {
70 id: 1,
71 winning_nums: vec![1, 2, 3, 4],
72 nums: vec![1, 2, 3]
73 }
74 )
75 }
76}