1#![warn(missing_docs)]
6#![allow(unreachable_pub)]
7#![allow(clippy::derive_partial_eq_without_eq)]
9
10use identifiers::expand_id_zst;
11use palpo_identifiers_validation::{
12 device_key_id, event_id, key_id, mxc_uri, room_alias_id, room_id, room_version_id, server_name, user_id,
13};
14use proc_macro::TokenStream;
15use proc_macro2 as pm2;
16use quote::quote;
17use syn::{parse_macro_input, DeriveInput, ItemEnum, ItemStruct};
18
19mod events;
20mod identifiers;
21mod serde;
22mod util;
23
24use self::{
25 events::{
26 event::expand_event,
27 event_content::expand_event_content,
28 event_enum::{expand_event_enums, expand_from_impls_derived},
29 event_parse::EventEnumInput,
30 event_type::expand_event_type_enum,
31 },
32 identifiers::IdentifierInput,
33 serde::{
34 as_str_as_ref_str::expand_as_str_as_ref_str,
35 debug_as_ref_str::expand_debug_as_ref_str,
36 deserialize_from_cow_str::expand_deserialize_from_cow_str,
37 display_as_ref_str::expand_display_as_ref_str,
38 enum_as_ref_str::expand_enum_as_ref_str,
39 enum_from_string::expand_enum_from_string,
40 eq_as_ref_str::expand_partial_eq_as_ref_str,
41 ord_as_ref_str::{expand_ord_as_ref_str, expand_partial_ord_as_ref_str},
42 serialize_as_ref_str::expand_serialize_as_ref_str,
43 },
44 util::import_palpo_core,
45};
46
47#[proc_macro]
74pub fn event_enum(input: TokenStream) -> TokenStream {
75 let event_enum_input = syn::parse_macro_input!(input as EventEnumInput);
76
77 let palpo_core = import_palpo_core();
78
79 let enums = event_enum_input
80 .enums
81 .iter()
82 .map(|e| expand_event_enums(e).unwrap_or_else(syn::Error::into_compile_error))
83 .collect::<pm2::TokenStream>();
84
85 let event_types =
86 expand_event_type_enum(event_enum_input, &palpo_core).unwrap_or_else(syn::Error::into_compile_error);
87
88 let tokens = quote! {
89 #enums
90 #event_types
91 };
92
93 tokens.into()
94}
95
96#[proc_macro_derive(EventContent, attributes(palpo_event))]
112pub fn derive_event_content(input: TokenStream) -> TokenStream {
113 let palpo_core = import_palpo_core();
114 let input = parse_macro_input!(input as DeriveInput);
115
116 expand_event_content(&input, &palpo_core)
117 .unwrap_or_else(syn::Error::into_compile_error)
118 .into()
119}
120
121#[proc_macro_derive(Event, attributes(palpo_event))]
123pub fn derive_event(input: TokenStream) -> TokenStream {
124 let input = parse_macro_input!(input as DeriveInput);
125 expand_event(input)
126 .unwrap_or_else(syn::Error::into_compile_error)
127 .into()
128}
129
130#[proc_macro_derive(EventEnumFromEvent)]
132pub fn derive_from_event_to_enum(input: TokenStream) -> TokenStream {
133 let input = parse_macro_input!(input as DeriveInput);
134 expand_from_impls_derived(input).into()
135}
136
137#[proc_macro_derive(IdZst, attributes(palpo_id))]
139pub fn derive_id_zst(input: TokenStream) -> TokenStream {
140 let input = parse_macro_input!(input as ItemStruct);
141 expand_id_zst(input)
142 .unwrap_or_else(syn::Error::into_compile_error)
143 .into()
144}
145
146#[proc_macro]
148pub fn device_key_id(input: TokenStream) -> TokenStream {
149 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
150 assert!(device_key_id::validate(&id.value()).is_ok(), "Invalid device key id");
151
152 let output = quote! {
153 <&#dollar_crate::DeviceKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
154 };
155
156 output.into()
157}
158
159#[proc_macro]
161pub fn event_id(input: TokenStream) -> TokenStream {
162 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
163 assert!(event_id::validate(&id.value()).is_ok(), "Invalid event id");
164
165 let output = quote! {
166 <&#dollar_crate::EventId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
167 };
168
169 output.into()
170}
171
172#[proc_macro]
174pub fn room_alias_id(input: TokenStream) -> TokenStream {
175 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
176 assert!(room_alias_id::validate(&id.value()).is_ok(), "Invalid room_alias_id");
177
178 let output = quote! {
179 <&#dollar_crate::RoomAliasId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
180 };
181
182 output.into()
183}
184
185#[proc_macro]
187pub fn room_id(input: TokenStream) -> TokenStream {
188 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
189 assert!(room_id::validate(&id.value()).is_ok(), "Invalid room_id");
190
191 let output = quote! {
192 <&#dollar_crate::RoomId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
193 };
194
195 output.into()
196}
197
198#[proc_macro]
200pub fn room_version_id(input: TokenStream) -> TokenStream {
201 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
202 assert!(
203 room_version_id::validate(&id.value()).is_ok(),
204 "Invalid room_version_id"
205 );
206
207 let output = quote! {
208 <#dollar_crate::RoomVersionId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
209 };
210
211 output.into()
212}
213
214#[proc_macro]
216pub fn server_signing_key_id(input: TokenStream) -> TokenStream {
217 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
218 assert!(key_id::validate(&id.value()).is_ok(), "Invalid server_signing_key_id");
219
220 let output = quote! {
221 <&#dollar_crate::ServerSigningKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
222 };
223
224 output.into()
225}
226
227#[proc_macro]
229pub fn server_name(input: TokenStream) -> TokenStream {
230 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
231 assert!(server_name::validate(&id.value()).is_ok(), "Invalid server_name");
232
233 let output = quote! {
234 <&#dollar_crate::ServerName as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
235 };
236
237 output.into()
238}
239
240#[proc_macro]
242pub fn mxc_uri(input: TokenStream) -> TokenStream {
243 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
244 assert!(mxc_uri::validate(&id.value()).is_ok(), "Invalid mxc://");
245
246 let output = quote! {
247 <&#dollar_crate::MxcUri as ::std::convert::From<&str>>::from(#id)
248 };
249
250 output.into()
251}
252
253#[proc_macro]
255pub fn user_id(input: TokenStream) -> TokenStream {
256 let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
257 assert!(user_id::validate(&id.value()).is_ok(), "Invalid user_id");
258
259 let output = quote! {
260 <&#dollar_crate::UserId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
261 };
262
263 output.into()
264}
265
266#[proc_macro_derive(AsRefStr, attributes(palpo_enum))]
268pub fn derive_enum_as_ref_str(input: TokenStream) -> TokenStream {
269 let input = parse_macro_input!(input as ItemEnum);
270 expand_enum_as_ref_str(&input)
271 .unwrap_or_else(syn::Error::into_compile_error)
272 .into()
273}
274
275#[proc_macro_derive(FromString, attributes(palpo_enum))]
277pub fn derive_enum_from_string(input: TokenStream) -> TokenStream {
278 let input = parse_macro_input!(input as ItemEnum);
279 expand_enum_from_string(&input)
280 .unwrap_or_else(syn::Error::into_compile_error)
281 .into()
282}
283
284#[proc_macro_derive(AsStrAsRefStr, attributes(palpo_enum))]
289pub fn derive_as_str_as_ref_str(input: TokenStream) -> TokenStream {
290 let input = parse_macro_input!(input as DeriveInput);
291 expand_as_str_as_ref_str(&input.ident)
292 .unwrap_or_else(syn::Error::into_compile_error)
293 .into()
294}
295
296#[proc_macro_derive(DisplayAsRefStr)]
298pub fn derive_display_as_ref_str(input: TokenStream) -> TokenStream {
299 let input = parse_macro_input!(input as DeriveInput);
300 expand_display_as_ref_str(&input.ident)
301 .unwrap_or_else(syn::Error::into_compile_error)
302 .into()
303}
304
305#[proc_macro_derive(DebugAsRefStr)]
307pub fn derive_debug_as_ref_str(input: TokenStream) -> TokenStream {
308 let input = parse_macro_input!(input as DeriveInput);
309 expand_debug_as_ref_str(&input.ident)
310 .unwrap_or_else(syn::Error::into_compile_error)
311 .into()
312}
313
314#[proc_macro_derive(SerializeAsRefStr)]
316pub fn derive_serialize_as_ref_str(input: TokenStream) -> TokenStream {
317 let input = parse_macro_input!(input as DeriveInput);
318 expand_serialize_as_ref_str(&input.ident)
319 .unwrap_or_else(syn::Error::into_compile_error)
320 .into()
321}
322
323#[proc_macro_derive(DeserializeFromCowStr)]
325pub fn derive_deserialize_from_cow_str(input: TokenStream) -> TokenStream {
326 let input = parse_macro_input!(input as DeriveInput);
327 expand_deserialize_from_cow_str(&input.ident)
328 .unwrap_or_else(syn::Error::into_compile_error)
329 .into()
330}
331
332#[proc_macro_derive(PartialOrdAsRefStr)]
334pub fn derive_partial_ord_as_ref_str(input: TokenStream) -> TokenStream {
335 let input = parse_macro_input!(input as DeriveInput);
336 expand_partial_ord_as_ref_str(&input.ident)
337 .unwrap_or_else(syn::Error::into_compile_error)
338 .into()
339}
340
341#[proc_macro_derive(OrdAsRefStr)]
343pub fn derive_ord_as_ref_str(input: TokenStream) -> TokenStream {
344 let input = parse_macro_input!(input as DeriveInput);
345 expand_ord_as_ref_str(&input.ident)
346 .unwrap_or_else(syn::Error::into_compile_error)
347 .into()
348}
349
350#[proc_macro_derive(PartialEqAsRefStr)]
352pub fn derive_partial_eq_as_ref_str(input: TokenStream) -> TokenStream {
353 let input = parse_macro_input!(input as DeriveInput);
354 expand_partial_eq_as_ref_str(&input.ident)
355 .unwrap_or_else(syn::Error::into_compile_error)
356 .into()
357}
358
359#[proc_macro_derive(StringEnum, attributes(palpo_enum))]
362pub fn derive_string_enum(input: TokenStream) -> TokenStream {
363 fn expand_all(input: ItemEnum) -> syn::Result<proc_macro2::TokenStream> {
364 let as_ref_str_impl = expand_enum_as_ref_str(&input)?;
365 let from_string_impl = expand_enum_from_string(&input)?;
366 let as_str_impl = expand_as_str_as_ref_str(&input.ident)?;
367 let display_impl = expand_display_as_ref_str(&input.ident)?;
368 let debug_impl = expand_debug_as_ref_str(&input.ident)?;
369 let serialize_impl = expand_serialize_as_ref_str(&input.ident)?;
370 let deserialize_impl = expand_deserialize_from_cow_str(&input.ident)?;
371
372 Ok(quote! {
373 #as_ref_str_impl
374 #from_string_impl
375 #as_str_impl
376 #display_impl
377 #debug_impl
378 #serialize_impl
379 #deserialize_impl
380 })
381 }
382
383 let input = parse_macro_input!(input as ItemEnum);
384 expand_all(input).unwrap_or_else(syn::Error::into_compile_error).into()
385}