makepad_live_id_macros/
lib.rs1use proc_macro::{TokenStream};
2
3use makepad_micro_proc_macro::{TokenBuilder, TokenParser, error};
4
5const LIVE_ID_SEED:u64 = 0xd6e8_feb8_6659_fd93;
6
7const fn from_bytes(seed:u64, id_bytes: &[u8], start: usize, end: usize) -> u64 {
8 let mut x = seed;
9 let mut i = start;
10 while i < end {
11 x = x.overflowing_add(id_bytes[i] as u64).0;
12 x ^= x >> 32;
13 x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
14 x ^= x >> 32;
15 x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
16 x ^= x >> 32;
17 i += 1;
18 }
19 (x & 0x7fff_ffff_ffff_ffff) | 0x8000_0000_0000_0000
21}
22
23const fn from_str_unchecked(id_str: &str) -> u64 {
24 let bytes = id_str.as_bytes();
25 from_bytes(LIVE_ID_SEED, bytes, 0, bytes.len())
26}
27
28mod derive_from_live_id;
29use crate::derive_from_live_id::*;
30
31#[proc_macro]
32pub fn live_id(item: TokenStream) -> TokenStream {
33 let mut tb = TokenBuilder::new();
34 let v = item.to_string();
35 let id = from_str_unchecked(&v);
36 tb.add("LiveId (").suf_u64(id).add(")");
37 tb.end()
38}
39
40#[proc_macro]
41pub fn some_id(item: TokenStream) -> TokenStream {
42 let mut tb = TokenBuilder::new();
43 let v = item.to_string();
44 let id = from_str_unchecked(&v);
45 tb.add("Some(LiveId (").suf_u64(id).add("))");
46 tb.end()
47}
48
49#[proc_macro]
50pub fn id(item: TokenStream) -> TokenStream {
51 let mut tb = TokenBuilder::new();
52 let mut parser = TokenParser::new(item);
53 fn parse(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
54 tb.add("&[");
55 loop{
56 if parser.open_paren(){
58 tb.stream(Some(parser.eat_level()));
59 tb.add(",");
60 }
61 else{
62 let ident = parser.expect_any_ident()?;
63 let id = from_str_unchecked(&ident);
64 tb.add("LiveId (").suf_u64(id).add("),");
65 }
66
67 if parser.eat_eot(){
68 tb.add("]");
69 return Ok(())
70 }
71 parser.expect_punct_alone('.')?
72 }
73 }
74 if let Err(e) = parse(&mut parser, &mut tb){
75 return e
76 };
77 tb.end()
78}
79
80#[proc_macro]
81pub fn ids(item: TokenStream) -> TokenStream {
82 let mut tb = TokenBuilder::new();
83 let mut parser = TokenParser::new(item);
84 fn parse(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
85 tb.add("&[");
86 'outer: loop{
87 tb.add("&[");
88 loop{
89 let ident = parser.expect_any_ident()?;
90 let id = from_str_unchecked(&ident);
91 tb.add("LiveId (").suf_u64(id).add("),");
92 if parser.eat_eot(){
93 tb.add("]");
94 break 'outer
95 }
96 if parser.eat_punct_alone(','){
97 tb.add("]");
98 break
99 }
100 parser.expect_punct_alone('.')?
101 }
102 tb.add(",");
103 if parser.eat_eot(){
104 break;
105 }
106 }
107 tb.add("]");
108 Ok(())
109 }
110 if let Err(e) = parse(&mut parser, &mut tb){
111 return e
112 };
113 tb.end()
114}
115
116
117#[proc_macro]
119pub fn live_id_num(item: TokenStream) -> TokenStream {
120 let mut tb = TokenBuilder::new();
121
122 let mut parser = TokenParser::new(item);
123 if let Some(name) = parser.eat_any_ident() {
124 if !parser.eat_punct_alone(','){
125 return error("please add a number")
126 }
127 let arg = parser.eat_level();
129 let id = from_str_unchecked(&name);
130 tb.add("LiveId::from_num(").suf_u64(id).add(",").stream(Some(arg)).add(")");
131 tb.end()
132 }
133 else{
134 parser.unexpected()
135 }
136}
137
138#[proc_macro]
139pub fn id_lut(item: TokenStream) -> TokenStream {
140 let mut tb = TokenBuilder::new();
141
142 let mut parser = TokenParser::new(item);
143 if let Some(name) = parser.eat_any_ident() {
144 tb.add("LiveId::from_str_with_lut(").string(&name).add(").unwrap()");
145 tb.end()
146 }
147 else if let Some(punct) = parser.eat_any_punct(){
148 tb.add("LiveId::from_str_with_lut(").string(&punct).add(").unwrap()");
149 tb.end()
150 }
151 else{
152 parser.unexpected()
153 }
154}
155
156#[proc_macro_derive(FromLiveId)]
157pub fn derive_from_live_id(input: TokenStream) -> TokenStream {
158 derive_from_live_id_impl(input)
159}