ct_regex_internal/codegen/create_type/
regex.rs

1use proc_macro2::{Span, TokenStream};
2use quote::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 Haystack = {
    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, "Haystack");
    _s
}quote!(::ct_regex::internal::haystack::Haystack);
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 pat_str = pat.value();
23
24    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!(
25        "A macro-generated regular expression matching the pattern: `{pat_str}` with flags: \
26        {flags}. See the [`Regex`](::ct_regex::internal::expr::Regex) trait for associated \
27        matching and capturing functions."
28        // TODO: Can be used for &str or &[u8]...
29    );
30
31    let mut config = flags.create_config();
32    config.unicode(false).utf8(false);
33
34    let (type_expr_byte, groups) = parse::parse_regex::<u8>(&pat_str, &config);
35
36    config.unicode(true).utf8(true);
37
38    let (type_expr_scalar, _) = parse::parse_regex::<char>(&pat_str, &config);
39
40    let (captures_name, captures_len, captures_impl) = capture::impl_captures(&vis, &name, groups);
41
42    let anon_impl = if impl_anon {
43        {
    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! {
44            impl #AnonRegex<u8, #captures_len> for #name {}
45
46            impl #AnonRegex<char, #captures_len> for #name {}
47        }
48    } else {
49        ::quote::__private::TokenStream::new()quote!()
50    };
51
52    {
    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::ToTokens::to_tokens(&vis, &mut _s);
    ::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, "H");
            ::quote::__private::push_colon(&mut _s);
            ::quote::ToTokens::to_tokens(&Haystack, &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, "H");
            ::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, "H");
            ::quote::__private::push_colon(&mut _s);
            ::quote::ToTokens::to_tokens(&Haystack, &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, "H");
            ::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! {
53        #[doc = #doc]
54        #vis struct #name;
55
56        impl #Regex<u8, #captures_len> for #name {
57            type Pattern = #type_expr_byte;
58
59            type Capture<'a, H: #Haystack<'a>> = #captures_name<'a, H>;
60        }
61
62        impl #Regex<char, #captures_len> for #name {
63            type Pattern = #type_expr_scalar;
64            type Capture<'a, H: #Haystack<'a>> = #captures_name<'a, H>;
65        }
66
67        #anon_impl
68
69        impl #fmt::Debug for #name {
70            fn fmt(&self, f: &mut #fmt::Formatter<'_>) -> #fmt::Result {
71                write!(f, "/{:?}/", <Self as #Regex<char, #captures_len>>::Pattern::default())
72            }
73        }
74
75        #captures_impl
76    }
77}
78
79pub fn make_anon_regex(AnonRegexArgs { pat, flags }: AnonRegexArgs) -> TokenStream {
80    let impl_tokens = make_regex(
81        RegexArgs {
82            vis: Visibility::Inherited,
83            name: Ident::new("__AnonRegex", Span::call_site()),
84            pat,
85            flags,
86        },
87        true
88    );
89    {
    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! {
90        {
91            #impl_tokens
92
93            __AnonRegex
94        }
95    }
96}