Skip to main content

typed_quote/tokens/
puncts.rs

1use super::*;
2
3#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
4trait Puncts<TS> {
5    type Puncts;
6    fn puncts(span: impl MaybeSpan) -> Self::Puncts;
7}
8
9#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
10macro_rules! puncts {
11    (($p0:literal, $p1:literal, $p2:literal $(,)?) $span:ident) => {
12        puncts![@[$p0 $p1][$p2] $span]
13    };
14    (($p0:literal, $p1:literal $(,)?) $span:ident) => {
15        puncts![@[$p0][$p1] $span]
16    };
17    (@[$($ch:literal)+][$last:literal] $span:ident) => {
18        puncts![
19            @@[
20                $(($ch Joint))+
21                ($last Alone)
22            ]
23            $span
24        ]
25    };
26    (@@[$(($ch:literal $spacing:ident))+] $span:ident) => {
27        [$(
28            pm::TokenTree::Punct(
29                (
30                    pm::Punct::new($ch, pm::Spacing::$spacing),
31                    $span,
32                ).into_st()
33            ),
34        )+]
35    };
36}
37
38#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
39macro_rules! count_literals {
40    ($($a:literal),+ $(,)?) => {
41        const { [$($a,)+].len() }
42    };
43}
44
45macro_rules! define_struct {
46    ({$(#$attrs:tt)*} $PunctGroup:ident) => {
47        $(#$attrs)*
48        pub struct $PunctGroup<S: MaybeSpan>(pub S);
49    };
50}
51
52macro_rules! define_structs {
53    ($attrs:tt [$($PunctGroup:ident)*]) => {
54        $(
55            define_struct! {
56                $attrs
57                $PunctGroup
58            }
59        )*
60    };
61}
62
63macro_rules! imp {
64    ({
65        $(#$attrs:tt)*
66        [$(
67            $PunctGroup:ident $chars:tt
68        ),+ $(,)?];
69
70        use $PS:ident;
71
72        $($imp:tt)*
73    }) => {
74        define_structs! {
75            {
76                $(#$attrs)*
77            }
78            [$($PunctGroup)+]
79        }
80
81        $(
82            crate::impl_many!({
83                {
84                    #[cfg(feature = "proc-macro")]
85                    {
86                        use proc_macro as pm;
87                    }
88                    #[cfg(feature = "proc-macro2")]
89                    {
90                        use proc_macro2 as pm;
91                    }
92                }
93
94                impl<S: MaybeSpan> Puncts<pm::TokenStream> for $PunctGroup<S> {
95                    type Puncts = [pm::TokenTree; count_literals! $chars];
96                    fn puncts(span: impl MaybeSpan) -> Self::Puncts {
97                        puncts!($chars span)
98                    }
99                }
100            });
101        )+
102
103        imp! {
104            @[$($PunctGroup)+]
105            $PS
106            [$($imp)*]
107        }
108    };
109    (
110        @[$($PunctGroup:ident)+]
111        $PS:ident
112        $imp:tt
113    ) => {
114        $(
115            const _: () = {
116                use $PunctGroup as $PS;
117
118                crate::expand_or! {$imp}
119            };
120        )+
121    };
122}
123
124imp!({
125    #[derive(Debug, Clone, Copy)]
126    [
127        Colon2(':', ':'),
128        AddEq('+', '='),
129        AndAnd('&', '&'),
130        AndEq('&', '='),
131        CaretEq('^', '='),
132        DivEq('/', '='),
133        Dot2('.', '.'),
134        Dot3('.', '.', '.'),
135        DotDotEq('.', '.', '='),
136        EqEq('=', '='),
137        Ge('>', '='),
138        Le('<', '='),
139        MulEq('*', '='),
140        Ne('!', '='),
141        OrEq('|', '='),
142        OrOr('|', '|'),
143        RArrow('-', '>'),
144        LArrow('<', '-'),
145        RemEq('%', '='),
146        FatArrow('=', '>'),
147        Shl('<', '<'),
148        ShlEq('<', '<', '='),
149        Shr('>', '>'),
150        ShrEq('>', '>', '='),
151        SubEq('-', '='),
152    ];
153    use PS;
154
155    impl<S: MaybeSpan> sealed::IntoTokens for PS<S> {}
156    impl<S: MaybeSpan> IntoTokens for PS<S> {
157        crate::impl_into_tokens!(
158            |self, ts| ts.extend(<Self as Puncts<pm::TokenStream>>::puncts(self.0)),
159            pm::TokenStream::from_iter(<Self as Puncts<pm::TokenStream>>::puncts(self.0)),
160        );
161    }
162
163    impl<S: MaybeSpan> sealed::ToTokens for PS<S> {}
164    impl<S: MaybeSpan> ToTokens for PS<S> {
165        crate::impl_to_tokens! {copy}
166    }
167
168    impl<SO: MaybeSpan> sealed::WithSpan for PS<SO> {}
169    impl<SO: MaybeSpan> WithSpan for PS<SO> {
170        type WithDefaultSpan<S: crate::Span> = PS<SO::WithDefaultSpan<S>>;
171
172        fn with_default_span<S: crate::Span>(self, span: S) -> Self::WithDefaultSpan<S> {
173            PS(self.0.with_default_span(span))
174        }
175
176        type WithReplacedSpan<S: crate::Span> = PS<SO::WithReplacedSpan<S>>;
177
178        fn with_replaced_span<S: crate::Span>(self, span: S) -> Self::WithReplacedSpan<S> {
179            PS(self.0.with_replaced_span(span))
180        }
181    }
182
183    impl<SO: MaybeSpan> sealed::RefWithSpan for PS<SO> {}
184    impl<SO: MaybeSpan> RefWithSpan for PS<SO> {
185        crate::impl_ref_with_span! {copy}
186    }
187});