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
extern crate proc_macro;
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
trait SplitPunct {
fn split_punct(&self, p: char) -> Vec<Vec<TokenTree>>;
}
impl SplitPunct for TokenStream {
fn split_punct(&self, p: char) -> Vec<Vec<TokenTree>> {
let tokenvec: Vec<TokenTree> = self.clone().into_iter().collect();
tokenvec
.split(|t| match t {
TokenTree::Punct(punct) => punct.as_char() == p,
_ => false,
})
.map(|i| i.into_iter().map(|ii| ii.clone()).collect())
.collect()
}
}
trait FromVecTokenTree {
fn make_token_stream(&self) -> TokenStream;
fn make_token_tree(&self) -> TokenTree;
}
impl FromVecTokenTree for Vec<TokenTree> {
fn make_token_stream(&self) -> TokenStream {
let mut t = TokenStream::new();
t.extend(self.clone());
t
}
fn make_token_tree(&self) -> TokenTree {
TokenTree::Group(Group::new(Delimiter::Brace, self.make_token_stream()))
}
}
fn begin(match_on: &Vec<TokenTree>) -> TokenStream {
let mut t = TokenStream::new();
t.extend(vec![
"match ".parse::<TokenStream>().unwrap(),
match_on.clone().make_token_stream(),
]);
t
}
thread_local! {
static ARROW: Vec<TokenTree> = vec![TokenTree::Punct(Punct::new('=', Spacing::Joint)), TokenTree::Punct(Punct::new('>', Spacing::Joint))];
}
#[proc_macro]
pub fn run(input: TokenStream) -> TokenStream {
let comma_split = input.split_punct(',');
let mut ret = begin(&comma_split[0]);
let split_input = match &comma_split[1][0] {
TokenTree::Group(g) => g.stream().split_punct('|'),
_ => panic!()
};
let run = vec![(&comma_split[2].clone()[0]).clone()];
let mut inner = Vec::new();
for match_ in split_input.iter() {
inner.extend(match_.clone());
inner.extend(vec![
TokenTree::Punct(Punct::new('=', Spacing::Joint)), TokenTree::Punct(Punct::new('>', Spacing::Joint))]);
inner.extend(run.clone());
}
if comma_split.len() > 3 {
inner.extend(vec![TokenTree::Ident(Ident::new("_", Span::call_site()))]);
#[allow(non_snake_case)]
inner.extend(ARROW.with(|A|A.clone()));
let run = vec![(&comma_split[3].clone()[0]).clone()];
inner.extend(run.clone());
} else {
inner.extend("_ => {}".parse::<TokenStream>().unwrap());
}
ret.extend(vec![inner.make_token_tree()]);
ret
}