const_dispatch_proc_macros/
_mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Crate not intended for direct use.
//! Use https:://docs.rs/const-dispatch instead.
// Templated by `cargo-generate` using https://github.com/danielhenrymantilla/proc-macro-template
#![allow(nonstandard_style, unused_imports)]

use ::core::{
    mem,
    ops::Not as _,
};
use ::proc_macro::*;

macro_rules! tts {
    [
        $($tt:expr),* $(,)?
    ] => (
        [
            $(
                TokenTree::from($tt),
            )*
        ]
        .into_iter()
    );
}

#[proc_macro_attribute]
#[doc(hidden)] /** Not part of the public API */ pub
fn ඞexterminate(
    args: TokenStream,
    _input: TokenStream,
) -> TokenStream
{
    assert!(args.is_empty());
    TokenStream::new()
}

#[proc_macro_derive(ConstDispatch)] pub
fn __(
    input: TokenStream
) -> TokenStream
{
    let to_be_braced = Iterator::chain(
        tts![
            Punct::new('#', proc_macro::Spacing::Alone),
            Group::new(
                Delimiter::Bracket,
                tts![
                    Punct::new(':', proc_macro::Spacing::Joint),
                    Punct::new(':', proc_macro::Spacing::Alone),
                    Ident::new("const_dispatch", Span::mixed_site()),
                    Punct::new(':', proc_macro::Spacing::Joint),
                    Punct::new(':', proc_macro::Spacing::Alone),
                    Ident::new("ඞ", Span::mixed_site()),
                    Punct::new(':', proc_macro::Spacing::Joint),
                    Punct::new(':', proc_macro::Spacing::Alone),
                    Ident::new("exterminate", Span::mixed_site()),
                ]
                .collect()
            )
        ],
        input,
    );
    tts![
        Punct::new(':', proc_macro::Spacing::Joint),
        Punct::new(':', proc_macro::Spacing::Alone),
        Ident::new("const_dispatch", Span::mixed_site()),
        Punct::new(':', proc_macro::Spacing::Joint),
        Punct::new(':', proc_macro::Spacing::Alone),
        Ident::new("ඞ", Span::mixed_site()),
        Punct::new(':', proc_macro::Spacing::Joint),
        Punct::new(':', proc_macro::Spacing::Alone),
        Ident::new("derive_ConstDispatch", Span::mixed_site()),
        Punct::new('!', proc_macro::Spacing::Alone),
        Group::new(Delimiter::Brace, to_be_braced.collect()),
    ].collect()
}

#[proc_macro]
#[doc(hidden)] /** Not part of the public API */ pub
fn ඞimpl_for_u8(
    _input: TokenStream,
) -> TokenStream
{
    // One-off helper macro.
    // Hygiene plays no role in the output, so we simplify the `syn`-less impl by using strings.
    let branches_const =
        (0..=u8::MAX)
            .map(|n| format!(r#"
                {n}_u8 => {{
                    const $C: ::core::primitive::u8 = $n;
                    $body
                }},
            "#))
            .collect::<String>()
    ;
    let branches_macro =
        (0..=u8::MAX)
            .map(|n| format!(r#"
                {n}_u8 => {{
                    __emit__! {{ $n }}
                }},
            "#))
            .collect::<String>()
    ;
    format!(r#"
        #[doc(hidden)]
        #[macro_export]
        macro_rules! u8 {{
            (
                $scrutinee:expr,
                |const $C:ident| $body:block
            ) => (
                match $scrutinee {{
                    {branches_const}
                }}
            );

            (
                $scrutinee:expr,
                $macro_input:tt => $macro_output:tt
            ) => ({{
                macro_rules! __emit__ {{ $macro_input => $macro_output }}
                match $scrutinee {{
                    {branches_macro}
                }}
            }});
        }}
    "#).parse().unwrap()
}