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