derive_atom_set/
lib.rs

1#![deny(warnings)]
2use proc_macro::TokenStream;
3use syn::{DeriveInput, parse_macro_input};
4
5mod atom_set;
6
7/// Derives an efficient `AtomSet` implementation for interned CSS identifiers.
8///
9/// This proc macro automatically generates optimized string-to-enum matching code.
10///
11/// ## Variant Attributes
12///
13/// - `#[default]`: Marks this variant as the empty/fallback value (returns empty string)
14/// - `#[atom("custom")]`: Overrides the default string representation
15///
16/// ## Naming Convention
17///
18/// If `#[atom("")]` is not provided a string is derived from the variant name:
19/// - `Px` → `"px"`
20/// - `FontSize` → `"font-size"`
21/// - `WebkitTransform` → `"webkit-transform"`
22///
23/// # Example
24///
25/// ```rust
26/// // Provide this trait definition:
27/// trait AtomSet {
28///     fn from_str(keyword: &str) -> Self;
29///     fn to_str(self) -> &'static str;
30///     fn len(&self) -> u32;
31///     fn from_bits(bits: u32) -> Self;
32///     fn as_bits(&self) -> u32;
33/// }
34/// use derive_atom_set::AtomSet;
35///
36/// #[derive(Debug, Default, Copy, Clone, PartialEq, AtomSet)]
37/// pub enum MyAtomSet {
38///     #[default]
39///     Unknown, // Must provide an empty default!
40///
41///     // Absolute units
42///     Px, Pt, Pc, In, Cm, Mm, Q,
43///
44///     // Relative units
45///     Em, Ex, Ch, Rem, Lh,
46///
47///     // Viewport units
48///     Vw, Vh, Vi, Vb, Vmin, Vmax,
49///
50///     // Container query units
51///     Cqw, Cqh, Cqi, Cqb, Cqmin, Cqmax,
52///
53///     // Special case
54///     #[atom("%")]
55///     Percent,
56/// }
57///
58/// // Usage:
59/// assert_eq!(MyAtomSet::from_str("px"), MyAtomSet::Px);
60/// assert_eq!(MyAtomSet::from_str("PX"), MyAtomSet::Px);  // Case insensitive matches
61/// assert_eq!(MyAtomSet::Px.to_str(), "px");
62/// assert_eq!(MyAtomSet::Percent.to_str(), "%");
63/// assert_eq!(MyAtomSet::from_str("unknown"), MyAtomSet::Unknown);
64/// ```
65#[proc_macro_derive(AtomSet, attributes(default, atom))]
66pub fn derive_atom_set(input: TokenStream) -> TokenStream {
67	let ast = parse_macro_input!(input as DeriveInput);
68	atom_set::generate(proc_macro2::TokenStream::new(), ast).into()
69}