opentalk_types_common_macros/
lib.rs1#![deny(
8 bad_style,
9 missing_debug_implementations,
10 missing_docs,
11 overflowing_literals,
12 patterns_in_fns_without_body,
13 trivial_casts,
14 trivial_numeric_casts,
15 unsafe_code,
16 unused,
17 unused_extern_crates,
18 unused_import_braces,
19 unused_qualifications,
20 unused_results
21)]
22
23use opentalk_types_common_identifiers::{
24 asset_file_kind::AssetFileKind, feature_id::FeatureId, module_id::ModuleId,
25};
26use proc_macro::TokenStream;
27use proc_macro_crate::{FoundCrate, crate_name};
28use proc_macro2::{Span, TokenStream as TokenStream2};
29use quote::quote;
30use syn::{LitStr, parse_macro_input};
31
32fn generate_const_id<T: std::str::FromStr + ToString>(
33 input: TokenStream,
34 path: TokenStream2,
35) -> TokenStream
36where
37 <T as std::str::FromStr>::Err: std::fmt::Display,
38{
39 let Ok(crate_name) = crate_name("opentalk-types-common") else {
40 return quote! { compile_error!("Couldn't find opentalk-types-common crate") }.into();
41 };
42
43 let crate_name = match crate_name {
44 FoundCrate::Itself => quote!(crate),
45 FoundCrate::Name(name) => {
46 let ident = proc_macro2::Ident::new(&name, Span::call_site());
47 quote!(#ident)
48 }
49 };
50
51 let input = parse_macro_input!(input as LitStr);
52 let value = input.value();
53
54 match value.parse::<T>() {
55 Ok(value) => {
56 let value = value.to_string();
57 quote! {
58 #crate_name::#path::__new_borrowed(#value)
59 }
60 }
61 Err(e) => {
62 let msg = e.to_string();
63 quote! { compile_error!(#msg) }
64 }
65 }
66 .into()
67}
68
69#[proc_macro]
71pub fn module_id(input: TokenStream) -> TokenStream {
72 generate_const_id::<ModuleId>(input, quote!(modules::ModuleId))
73}
74
75#[proc_macro]
77pub fn feature_id(input: TokenStream) -> TokenStream {
78 generate_const_id::<FeatureId>(input, quote!(features::FeatureId))
79}
80
81#[proc_macro]
83pub fn asset_file_kind(input: TokenStream) -> TokenStream {
84 generate_const_id::<AssetFileKind>(input, quote!(assets::AssetFileKind))
85}