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
use std::collections::HashSet;
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse::Parse;
use syn::{parse_macro_input, Ident, Token};
struct InputConsumerMacro {
name: Ident,
types: Vec<Ident>,
}
impl Parse for InputConsumerMacro {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut types: Vec<Ident> = Vec::new();
let name: Ident = input.parse()?;
input.parse::<Token![;]>()?;
while !input.is_empty() {
let ty: Ident = input.parse()?;
types.push(ty);
if !input.is_empty() {
input.parse::<Token![,]>()?;
}
}
Ok(InputConsumerMacro { name, types })
}
}
#[proc_macro]
pub fn derive_input_consumer(input: TokenStream) -> TokenStream {
let mut subtypes_str: HashSet<&str> = HashSet::from([
"AnyButtonConsumer",
"ButtonConsumer",
"HotkeyConsumer",
"CursorPositionConsumer",
"CursorMotionConsumer",
"ScrollConsumer",
"ResizeConsumer",
"FocusConsumer",
"CursorInWindowConsumer",
"CloseConsumer",
]);
let InputConsumerMacro { name, types } = parse_macro_input!(input as InputConsumerMacro);
for ty in types {
subtypes_str.remove(ty.to_string().as_str());
}
let mut subtypes: Vec<Ident> = Vec::new();
for t in subtypes_str {
subtypes.push(format_ident!("{}", t));
}
let iter = subtypes.iter();
let expanded = quote! {
impl InputConsumer for #name {}
impl<'a> From<&'a mut #name> for &'a mut dyn InputConsumer {
fn from(val: &'a mut #name) -> Self {
val as &'a mut dyn InputConsumer
}
}
use input::*;
#(impl #iter for #name {fn accepts(&self) -> bool {false}})*
};
TokenStream::from(expanded)
}
#[test]
fn test() {
assert_eq!(
syn::parse_str::<Ident>("Hello").unwrap().to_string(),
"Hello"
);
}