Skip to main content

nearest_derive/
lib.rs

1//! Derive macros for the `nearest` crate.
2
3mod emit;
4mod emit_proxy;
5mod flat;
6mod util;
7
8use proc_macro::TokenStream;
9use quote::quote;
10use syn::{Data, parse_macro_input};
11
12/// Derive `Flat` and `Emit` for region-based storage.
13///
14/// Generates implementations for both the `Flat` marker trait and the `Emit`
15/// builder trait, enabling declarative region construction.
16#[proc_macro_derive(Flat)]
17pub fn derive_flat(input: TokenStream) -> TokenStream {
18  let input = parse_macro_input!(input as syn::DeriveInput);
19  if let Data::Union(ref u) = input.data {
20    return TokenStream::from(
21      syn::Error::new_spanned(u.union_token, "Flat cannot be derived for unions")
22        .to_compile_error(),
23    );
24  }
25  if let Data::Enum(ref data) = input.data
26    && let Some(err) = flat::validate_enum(&input, data)
27  {
28    return TokenStream::from(err);
29  }
30  let flat_impl = flat::gen_flat_impl(&input);
31  let emit_impl = emit::gen_emit_impl(&input);
32  TokenStream::from(quote! { #flat_impl #emit_impl })
33}
34
35/// Derive [`Emit<T>`] for a proxy enum that dispatches to inner builders.
36///
37/// Each variant must be a single-field newtype. The target type is specified
38/// via `#[emit(TargetType)]`. All generic type parameters receive an
39/// `Emit<TargetType>` bound.
40///
41/// # Example
42///
43/// ```ignore
44/// #[derive(Emit)]
45/// #[emit(Block)]
46/// enum BlockEmit<A, B, C> {
47///   Br(A),
48///   Brif(B),
49///   Call(C),
50/// }
51/// ```
52///
53/// This generates `unsafe impl<A: Emit<Block>, B: Emit<Block>, C: Emit<Block>> Emit<Block> for BlockEmit<A, B, C>`,
54/// where each variant delegates `write_at` to its inner value.
55#[proc_macro_derive(Emit, attributes(emit))]
56pub fn derive_emit(input: TokenStream) -> TokenStream {
57  let input = parse_macro_input!(input as syn::DeriveInput);
58  TokenStream::from(emit_proxy::gen_emit_proxy(&input))
59}