Skip to main content

alux_shape_macros/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod layout;
4mod shape;
5mod words;
6mod written;
7
8use proc_macro::TokenStream;
9use syn::{DeriveInput, parse_macro_input};
10
11/// States `ShapeOf` for a layout, reading its members and their names from the type.
12#[proc_macro_derive(Shape, attributes(written))]
13pub fn derive_shape(input: TokenStream) -> TokenStream {
14    let input = parse_macro_input!(input as DeriveInput);
15
16    shape::expand(input).unwrap_or_else(syn::Error::into_compile_error).into()
17}
18
19/// Emits the layouts a block of shape declarations states, beside the declarations themselves.
20///
21/// Written outside `#[ext(… defunc(via = shape))]`, which it re-emits untouched:
22///
23/// ```rust ignore
24/// #[shape_layout]
25/// #[ext(name = UserShapeExt, defunc(via = shape))]
26/// pub impl<This> This
27/// where
28///     This: ShapeAlg + FieldAlg,
29/// {
30///     fn user_shape(&self) {
31///         self.record().field::<String>(display_name, self.text())
32///     }
33/// }
34/// ```
35///
36/// Each member states the type carrying it, which is what a layout is emitted from. An optional
37/// argument states how the layout writes its names, defaulting to `"camelCase"`.
38///
39/// The emitted layout derives `serde::Serialize` and `serde::Deserialize`, so a crate using this needs
40/// `serde` among its dependencies.
41#[proc_macro_attribute]
42pub fn shape_layout(attr: TokenStream, item: TokenStream) -> TokenStream {
43    layout::expand(attr.into(), item.into()).unwrap_or_else(syn::Error::into_compile_error).into()
44}