ct_regex_internal/codegen/
args.rs

1use std::{collections::HashSet, fmt::{self, Display}};
2
3use syn::{Ident, LitStr, Token, Visibility, parse::{Parse, ParseStream}};
4
5use crate::codegen::ConfigExt;
6
7pub enum RegexArgType {
8    Regex(RegexArgs),
9    Anon(AnonRegexArgs),
10}
11
12impl Parse for RegexArgType {
13    fn parse(input: ParseStream) -> syn::Result<Self> {
14        if input.fork().parse::<RegexArgs>().is_ok() {
15            Ok(RegexArgType::Regex(input.parse()?))
16        } else {
17            Ok(RegexArgType::Anon(input.parse()?))
18        }
19    }
20}
21
22pub struct RegexArgs {
23    pub vis: Visibility,
24    pub name: Ident,
25    pub pat: LitStr,
26    pub flags: Flags,
27}
28
29impl Parse for RegexArgs {
30    fn parse(input: ParseStream) -> syn::Result<Self> {
31        let vis = input.parse()?;
32        let name = input.parse()?;
33        input.parse::<Token![=]>()?;
34        let pat = input.parse()?;
35        let flags = input.parse()?;
36        Ok(RegexArgs {
37            vis,
38            name,
39            pat,
40            flags,
41        })
42    }
43}
44
45pub struct AnonRegexArgs {
46    pub pat: LitStr,
47    pub flags: Flags,
48}
49
50impl Parse for AnonRegexArgs {
51    fn parse(input: ParseStream) -> syn::Result<Self> {
52        Ok(AnonRegexArgs {
53            pat: input.parse()?,
54            flags: input.parse()?,
55        })
56    }
57}
58
59pub struct Flags(pub HashSet<char>);
60
61impl Parse for Flags {
62    fn parse(input: ParseStream) -> syn::Result<Self> {
63        let sep = input.parse::<Token![/]>();
64
65        let lit: syn::Result<LitStr> = input.parse();
66
67        let set = lit
68            .and_then(|l| sep.map(|_| l))
69            .map(|l| l.value())
70            .unwrap_or_default()
71            .chars()
72            .collect();
73
74        Ok(Flags(set))
75    }
76}
77
78impl Flags {
79    pub fn create_config(self) -> ConfigExt {
80        let mut config = ConfigExt::default();
81
82        for c in self.0 {
83            match c {
84                'i' => config.case_insensitive(true),
85                'm' => config.multi_line(true),
86                's' => config.dot_matches_new_line(true),
87                'R' => config.crlf(true),
88                'U' => config.swap_greed(true),
89                'x' => config.ignore_whitespace(true),
90                'c' => config.complex_classes(true),
91                'g' => {
    ::core::panicking::panic_fmt(format_args!("the global flag is unsupported by this implementation, please read the docs on the methods available on the Regex trait"));
}panic!("the global flag is unsupported by this implementation, please read \
92                    the docs on the methods available on the Regex trait"),
93                o => {
    ::core::panicking::panic_fmt(format_args!("unknown flag provided for regex: {0:?}",
            o));
}panic!("unknown flag provided for regex: {o:?}"),
94            };
95        }
96
97        config
98    }
99}
100
101impl Display for Flags {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        let mut vec: Vec<_> = self.0.iter().collect();
104        vec.sort();
105        f.write_fmt(format_args!("{0:?}", &vec[..]))write!(f, "{:?}", &vec[..])
106    }
107}