Skip to main content

ct_regex_internal/codegen/
args.rs

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