regex_parse/
lib.rs

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}