Skip to main content

opentalk_types_common_macros/
lib.rs

1// SPDX-FileCopyrightText: OpenTalk GmbH <mail@opentalk.eu>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5//! Macros for opentalk-types-common.
6
7#![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/// Create a constant `ModuleId` at compile time.
70#[proc_macro]
71pub fn module_id(input: TokenStream) -> TokenStream {
72    generate_const_id::<ModuleId>(input, quote!(modules::ModuleId))
73}
74
75/// Create a constant `FeatureId` at compile time.
76#[proc_macro]
77pub fn feature_id(input: TokenStream) -> TokenStream {
78    generate_const_id::<FeatureId>(input, quote!(features::FeatureId))
79}
80
81/// Create a constant `AssetFileKind` at compile time.
82#[proc_macro]
83pub fn asset_file_kind(input: TokenStream) -> TokenStream {
84    generate_const_id::<AssetFileKind>(input, quote!(assets::AssetFileKind))
85}