Skip to main content

ct_regex_internal/codegen/create_type/
regex.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{format_ident, quote};
3use syn::{Ident, Visibility};
4
5use crate::codegen::{AnonRegexArgs, RegexArgs, capture, parse};
6
7pub fn make_regex(
8    RegexArgs {
9        vis,
10        name,
11        pat,
12        flags,
13    }: RegexArgs,
14    impl_anon: bool,
15) -> TokenStream {
16    #![allow(nonstandard_style)]
17    let fmt = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "std");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "fmt");
    _s
}quote!(::std::fmt);
18    let HaystackSlice = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "haystack");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "HaystackSlice");
    _s
}quote!(::ct_regex::internal::haystack::HaystackSlice);
19    let Regex = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expr");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Regex");
    _s
}quote!(::ct_regex::internal::expr::Regex);
20    let AnonRegex = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ct_regex");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expr");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "AnonRegex");
    _s
}quote!(::ct_regex::internal::expr::AnonRegex);
21
22    let mod_name = match ::quote::__private::IdentFragmentAdapter(&&name) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("__regex_{0}", arg))
                    }), ::quote::__private::Option::None.or(arg.span())),
}format_ident!("__regex_{}", &name);
23
24    let pat_str = pat.value();
25
26    let doc = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("A macro-generated regular expression matching the pattern: `{0}` with flags: {1}. See the [`Regex`](::ct_regex::internal::expr::Regex) trait for associated matching and capturing functions.",
                pat_str, flags))
    })format!(
27        "A macro-generated regular expression matching the pattern: `{pat_str}` with flags: \
28        {flags}. See the [`Regex`](::ct_regex::internal::expr::Regex) trait for associated \
29        matching and capturing functions." // TODO: Can be used for &str or &[u8]...
30    );
31
32    let mut config = flags.create_config();
33    config.unicode(false).utf8(false);
34
35    let (type_expr_byte, groups) = parse::parse_regex::<u8>(&pat_str, &config);
36
37    config.unicode(true).utf8(true);
38
39    let (type_expr_scalar, _) = parse::parse_regex::<char>(&pat_str, &config);
40
41    let (captures_name, captures_len, captures_impl) = capture::impl_captures(&name, groups);
42
43    let anon_impl = if impl_anon {
44        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&AnonRegex, &mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "u8");
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&captures_len, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&AnonRegex, &mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "char");
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&captures_len, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
45            impl #AnonRegex<u8, #captures_len> for #name {}
46
47            impl #AnonRegex<char, #captures_len> for #name {}
48        }
49    } else {
50        ::quote::__private::TokenStream::new()quote!()
51    };
52
53    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "hidden");
                    _s
                });
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "allow");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "non_snake_case");
                    _s
                });
            _s
        });
    ::quote::__private::push_ident(&mut _s, "mod");
    ::quote::ToTokens::to_tokens(&mod_name, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "doc");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&doc, &mut _s);
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "pub");
            ::quote::__private::push_ident(&mut _s, "struct");
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "impl");
            ::quote::ToTokens::to_tokens(&Regex, &mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "u8");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&captures_len, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "type");
                    ::quote::__private::push_ident(&mut _s, "Pattern");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&type_expr_byte, &mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "type");
                    ::quote::__private::push_ident(&mut _s, "Capture");
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "S");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::ToTokens::to_tokens(&HaystackSlice, &mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_shr(&mut _s);
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&captures_name, &mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "S");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "impl");
            ::quote::ToTokens::to_tokens(&Regex, &mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "char");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&captures_len, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "type");
                    ::quote::__private::push_ident(&mut _s, "Pattern");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&type_expr_scalar, &mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "type");
                    ::quote::__private::push_ident(&mut _s, "Capture");
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "S");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::ToTokens::to_tokens(&HaystackSlice, &mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_shr(&mut _s);
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::ToTokens::to_tokens(&captures_name, &mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_lifetime(&mut _s, "\'a");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "S");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_semi(&mut _s);
                    _s
                });
            ::quote::ToTokens::to_tokens(&anon_impl, &mut _s);
            ::quote::__private::push_ident(&mut _s, "impl");
            ::quote::ToTokens::to_tokens(&fmt, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Debug");
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "fn");
                    ::quote::__private::push_ident(&mut _s, "fmt");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_and(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "self");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "f");
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::__private::push_and(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mut");
                            ::quote::ToTokens::to_tokens(&fmt, &mut _s);
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Formatter");
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::__private::push_lifetime(&mut _s, "\'_");
                            ::quote::__private::push_gt(&mut _s);
                            _s
                        });
                    ::quote::__private::push_rarrow(&mut _s);
                    ::quote::ToTokens::to_tokens(&fmt, &mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Result");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "write");
                            ::quote::__private::push_bang(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "f");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::parse(&mut _s, "\"/{:?}/\"");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::__private::push_lt(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Self");
                                    ::quote::__private::push_ident(&mut _s, "as");
                                    ::quote::ToTokens::to_tokens(&Regex, &mut _s);
                                    ::quote::__private::push_lt(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "char");
                                    ::quote::__private::push_comma(&mut _s);
                                    ::quote::ToTokens::to_tokens(&captures_len, &mut _s);
                                    ::quote::__private::push_shr(&mut _s);
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Pattern");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "default");
                                    ::quote::__private::push_group(&mut _s,
                                        ::quote::__private::Delimiter::Parenthesis,
                                        ::quote::__private::TokenStream::new());
                                    _s
                                });
                            _s
                        });
                    _s
                });
            ::quote::ToTokens::to_tokens(&captures_impl, &mut _s);
            _s
        });
    ::quote::__private::push_pound(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "doc");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            _s
        });
    ::quote::ToTokens::to_tokens(&vis, &mut _s);
    ::quote::__private::push_ident(&mut _s, "use");
    ::quote::ToTokens::to_tokens(&mod_name, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_star(&mut _s);
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
54        #[doc(hidden)]
55        #[allow(non_snake_case)]
56        mod #mod_name {
57            #[doc = #doc]
58            pub struct #name;
59
60            impl #Regex<u8, #captures_len> for #name {
61                type Pattern = #type_expr_byte;
62
63                type Capture<'a, S: #HaystackSlice<'a>> = #captures_name<'a, S>;
64            }
65
66            impl #Regex<char, #captures_len> for #name {
67                type Pattern = #type_expr_scalar;
68                type Capture<'a, S: #HaystackSlice<'a>> = #captures_name<'a, S>;
69            }
70
71            #anon_impl
72
73            impl #fmt::Debug for #name {
74                fn fmt(&self, f: &mut #fmt::Formatter<'_>) -> #fmt::Result {
75                    write!(f, "/{:?}/", <Self as #Regex<char, #captures_len>>::Pattern::default())
76                }
77            }
78
79            #captures_impl
80        }
81
82        #[doc(inline)]
83        #vis use #mod_name::*;
84    }
85}
86
87pub fn make_anon_regex(AnonRegexArgs { pat, flags }: AnonRegexArgs) -> TokenStream {
88    let impl_tokens = make_regex(
89        RegexArgs {
90            vis: Visibility::Inherited,
91            name: Ident::new("__AnonRegex", Span::call_site()),
92            pat,
93            flags,
94        },
95        true,
96    );
97    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&impl_tokens, &mut _s);
            ::quote::__private::push_ident(&mut _s, "__AnonRegex");
            _s
        });
    _s
}quote! {
98        {
99            #impl_tokens
100
101            __AnonRegex
102        }
103    }
104}