qcontext_derive/
lib.rs

1use darling::FromDeriveInput;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput, Ident, Type};
4
5#[derive(Debug, FromDeriveInput)]
6#[darling(attributes(context))]
7struct ContextDeriveInput {
8  ident: Ident,
9  state: Type,
10}
11
12/// Implements [Context](https://docs.rs/qcontext/latest/qcontext/trait.Context.html)
13///
14/// ## Attributes
15///
16/// * `#[context(state = "TCell<Context, usize>")]` sets [`Context::State`](https://docs.rs/qcontext/latest/qcontext/trait.Context.htmll#associatedtype.State)
17#[proc_macro_derive(Context, attributes(context))]
18pub fn derive_context(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
19  let input = parse_macro_input!(input as DeriveInput);
20
21  let ContextDeriveInput { ident, state } = match ContextDeriveInput::from_derive_input(&input) {
22    Ok(input) => input,
23    Err(err) => return err.write_errors().into(),
24  };
25
26  let expanded = quote! {
27    impl qcontext::Context for #ident {
28      type State = #state;
29
30      fn context() -> &'static qcontext::OnceCell<Self::State> {
31        static CONTEXT: qcontext::OnceCell<#state> = qcontext::OnceCell::new();
32
33        &CONTEXT
34      }
35    }
36  };
37
38  expanded.into()
39}