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
35 let mut parser = TokenParser::new(item);
36 if let Some(name) = parser.eat_any_ident() {
37 let id = from_str_unchecked(&name);
38 tb.add("LiveId (").suf_u64(id).add(")");
39 tb.end()
40 }
41 else if let Some(punct) = parser.eat_any_punct(){
42 let id = from_str_unchecked(&punct);
43 tb.add("LiveId (").suf_u64(id).add(")");
44 tb.end()
45 }
46 else if let Some(v) = parser.eat_literal(){
47 if let Ok(v) = v.to_string().parse::<u64>(){
48 tb.add("LiveId (").suf_u64(v).add(")");
49 return tb.end()
50 }
51 else{
52 parser.unexpected()
53 }
54 }
55 else{
56 parser.unexpected()
57 }
58}
59
60#[proc_macro]
61pub fn id(item: TokenStream) -> TokenStream {
62 let mut tb = TokenBuilder::new();
63 let mut parser = TokenParser::new(item);
64 fn parse(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
65 tb.add("&[");
66 loop{
67 let ident = parser.expect_any_ident()?;
68 let id = from_str_unchecked(&ident);
69 tb.add("LiveId (").suf_u64(id).add("),");
70 if parser.eat_eot(){
71 tb.add("]");
72 return Ok(())
73 }
74 parser.expect_punct_alone('.')?
75 }
76 }
77 if let Err(e) = parse(&mut parser, &mut tb){
78 return e
79 };
80 tb.end()
81}
82
83#[proc_macro]
84pub fn ids(item: TokenStream) -> TokenStream {
85 let mut tb = TokenBuilder::new();
86 let mut parser = TokenParser::new(item);
87 fn parse(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
88 tb.add("&[");
89 'outer: loop{
90 tb.add("&[");
91 loop{
92 let ident = parser.expect_any_ident()?;
93 let id = from_str_unchecked(&ident);
94 tb.add("LiveId (").suf_u64(id).add("),");
95 if parser.eat_eot(){
96 tb.add("]");
97 break 'outer
98 }
99 if parser.eat_punct_alone(','){
100 tb.add("]");
101 break
102 }
103 parser.expect_punct_alone('.')?
104 }
105 tb.add(",");
106 if parser.eat_eot(){
107 break;
108 }
109 }
110 tb.add("]");
111 Ok(())
112 }
113 if let Err(e) = parse(&mut parser, &mut tb){
114 return e
115 };
116 tb.end()
117}
118
119
120#[proc_macro]
122pub fn live_id_num(item: TokenStream) -> TokenStream {
123 let mut tb = TokenBuilder::new();
124
125 let mut parser = TokenParser::new(item);
126 if let Some(name) = parser.eat_any_ident() {
127 if !parser.eat_punct_alone(','){
128 return error("please add a number")
129 }
130 let arg = parser.eat_level();
132 let id = from_str_unchecked(&name);
133 tb.add("LiveId::from_num(").suf_u64(id).add(",").stream(Some(arg)).add(")");
134 tb.end()
135 }
136 else{
137 parser.unexpected()
138 }
139}
140
141#[proc_macro]
142pub fn id_lut(item: TokenStream) -> TokenStream {
143 let mut tb = TokenBuilder::new();
144
145 let mut parser = TokenParser::new(item);
146 if let Some(name) = parser.eat_any_ident() {
147 tb.add("LiveId::from_str_with_lut(").string(&name).add(").unwrap()");
148 tb.end()
149 }
150 else if let Some(punct) = parser.eat_any_punct(){
151 tb.add("LiveId::from_str_with_lut(").string(&punct).add(").unwrap()");
152 tb.end()
153 }
154 else{
155 parser.unexpected()
156 }
157}
158
159#[proc_macro_derive(FromLiveId)]
160pub fn derive_from_live_id(input: TokenStream) -> TokenStream {
161 derive_from_live_id_impl(input)
162}