const_dispatch_proc_macros/
_mod.rs1#![allow(nonstandard_style, unused_imports)]
5
6use ::core::{
7 mem,
8 ops::Not as _,
9};
10use ::proc_macro::*;
11
12macro_rules! tts {
13 [
14 $($tt:expr),* $(,)?
15 ] => (
16 [
17 $(
18 TokenTree::from($tt),
19 )*
20 ]
21 .into_iter()
22 .collect::<TokenStream>()
23 );
24}
25
26#[proc_macro_attribute]
27#[doc(hidden)] pub
28fn ඞexterminate(
29 args: TokenStream,
30 _input: TokenStream,
31) -> TokenStream
32{
33 assert!(args.is_empty());
34 TokenStream::new()
35}
36
37#[proc_macro_derive(ConstDispatch)] pub
38fn __(
39 input: TokenStream
40) -> TokenStream
41{
42 let to_be_braced = Iterator::chain(
43 tts![
44 Punct::new('#', Spacing::Alone),
45 Group::new(
46 Delimiter::Bracket,
47 tts![
48 Punct::new(':', Spacing::Joint),
49 Punct::new(':', Spacing::Alone),
50 Ident::new("const_dispatch", Span::mixed_site()),
51 Punct::new(':', Spacing::Joint),
52 Punct::new(':', Spacing::Alone),
53 Ident::new("ඞ", Span::mixed_site()),
54 Punct::new(':', Spacing::Joint),
55 Punct::new(':', Spacing::Alone),
56 Ident::new("exterminate", Span::mixed_site()),
57 ]
58 )
59 ]
60 .into_iter()
61 ,
62 input,
63 );
64 tts![
65 Punct::new(':', Spacing::Joint),
66 Punct::new(':', Spacing::Alone),
67 Ident::new("const_dispatch", Span::mixed_site()),
68 Punct::new(':', Spacing::Joint),
69 Punct::new(':', Spacing::Alone),
70 Ident::new("ඞ", Span::mixed_site()),
71 Punct::new(':', Spacing::Joint),
72 Punct::new(':', Spacing::Alone),
73 Ident::new("derive_ConstDispatch", Span::mixed_site()),
74 Punct::new('!', Spacing::Alone),
75 Group::new(Delimiter::Brace, to_be_braced.collect()),
76 ]
77}
78
79#[proc_macro]
80#[doc(hidden)] pub
81fn ඞimpl_for_u8(
82 _input: TokenStream,
83) -> TokenStream
84{
85 let branches_const =
88 (0..=u8::MAX)
89 .map(|n| format!(r#"
90 {n}_u8 => {{
91 const $C: ::core::primitive::u8 = {n};
92 {{
93 $crate::ඞ::try_hide!($scrutinee);
94 $body
95 }}
96 }},
97 "#))
98 .collect::<String>()
99 ;
100 let branches_macro =
101 (0..=u8::MAX)
102 .map(|n| format!(r#"
103 {n}_u8 => {{
104 $crate::ඞ::try_hide!($scrutinee);
105 __emit__! {{ {n} }}
106 }},
107 "#))
108 .collect::<String>()
109 ;
110 format!(r#"
111 #[doc(hidden)]
112 #[macro_export]
113 macro_rules! u8 {{
114 (
115 $scrutinee:expr,
116 |const $C:ident| $body:block
117 ) => (
118 match $scrutinee {{
119 {branches_const}
120 }}
121 );
122
123 (
124 $scrutinee:expr,
125 $macro_input:tt => $macro_output:tt
126 ) => ({{
127 macro_rules! __emit__ {{ $macro_input => $macro_output }}
128 match $scrutinee {{
129 {branches_macro}
130 }}
131 }});
132 }}
133 "#).parse().unwrap()
134}
135
136#[proc_macro]
139#[doc(hidden)] pub
140fn ඞtry_hide(
141 input: TokenStream,
142) -> TokenStream
143{
144 let ident = match input.into_iter().next().unwrap() {
145 TokenTree::Group(g) if g.delimiter() == Delimiter::None => {
146 let mut inner_tts = g.stream().into_iter();
147 match (inner_tts.next(), inner_tts.next()) {
148 (Some(TokenTree::Ident(ident)), None) if ident.to_string() != "self" => ident,
149 _ => return <_>::default(),
150 }
151 },
152 TokenTree::Ident(ident) if ident.to_string() != "self" => ident,
154 _ => return <_>::default(),
155 };
156 let allow_unused = Group::new(
157 Delimiter::Bracket,
158 tts![
159 Ident::new("allow", Span::mixed_site()),
160 Group::new(
161 Delimiter::Parenthesis,
162 tts![
163 Ident::new("unused", Span::mixed_site()),
164 ],
165 ),
166 ],
167 );
168 tts![
169 Punct::new('#', Spacing::Alone), allow_unused.clone(),
170 Ident::new("fn", Span::mixed_site()),
172 ident.clone(),
173 Group::new(Delimiter::Parenthesis, <_>::default()),
174 Group::new(Delimiter::Brace, <_>::default()),
175
176 Punct::new('#', Spacing::Alone), allow_unused,
177 Ident::new("let", Span::mixed_site()),
179 ident,
180 Punct::new(':', Spacing::Alone),
181
182 Punct::new(':', Spacing::Joint),
183 Punct::new(':', Spacing::Alone),
184 Ident::new("const_dispatch", Span::mixed_site()),
185 Punct::new(':', Spacing::Joint),
186 Punct::new(':', Spacing::Alone),
187 Ident::new("ඞ", Span::mixed_site()),
188 Punct::new(':', Spacing::Joint),
189 Punct::new(':', Spacing::Alone),
190 Ident::new("Never", Span::mixed_site()),
191
192 Punct::new(';', Spacing::Alone),
193 ]
194}