luars_derive/lib.rs
1//! Procedural macros for luars userdata system.
2//!
3//! # Macros provided
4//!
5//! - `#[derive(LuaUserData)]` — auto-generate `UserDataTrait` for structs
6//! (field access via `get_field`/`set_field`, metamethods via `#[lua_impl(...)]`)
7//!
8//! - `#[lua_methods]` — attribute macro on impl blocks, generates static C wrapper
9//! functions for each `pub fn`, accessible from Lua via `obj:method(...)` calls
10//!
11//! # Architecture
12//!
13//! - `derive_userdata.rs` — `#[derive(LuaUserData)]` implementation
14//! - `lua_methods.rs` — `#[lua_methods]` implementation
15//! - `type_utils.rs` — shared type conversion helpers (Rust ↔ UdValue ↔ LuaValue)
16
17mod derive_userdata;
18mod lua_methods;
19mod type_utils;
20
21use proc_macro::TokenStream;
22use syn::parse_macro_input;
23
24/// Derive `UserDataTrait` for a struct, exposing public fields to Lua.
25///
26/// # Supported field types (auto-converted to/from UdValue)
27/// - `i8`..`i64`, `isize` → `UdValue::Integer`
28/// - `u8`..`u64`, `usize` → `UdValue::Integer`
29/// - `f32`, `f64` → `UdValue::Number`
30/// - `bool` → `UdValue::Boolean`
31/// - `String` → `UdValue::Str`
32///
33/// # Field attributes
34/// - `#[lua(skip)]` — exclude from Lua
35/// - `#[lua(readonly)]` — get only, no set
36/// - `#[lua(name = "...")]` — custom Lua name
37///
38/// # Struct attributes
39/// - `#[lua_impl(Display, PartialEq, PartialOrd)]` — metamethods from Rust traits
40///
41/// # Example
42/// ```ignore
43/// #[derive(LuaUserData, PartialEq, PartialOrd)]
44/// #[lua_impl(Display, PartialEq, PartialOrd)]
45/// struct Point {
46/// pub x: f64,
47/// pub y: f64,
48/// #[lua(skip)]
49/// internal_id: u32,
50/// }
51/// ```
52#[proc_macro_derive(LuaUserData, attributes(lua, lua_impl))]
53pub fn derive_lua_userdata(input: TokenStream) -> TokenStream {
54 let input = parse_macro_input!(input as syn::DeriveInput);
55 derive_userdata::derive_lua_userdata_impl(input)
56}
57
58/// Attribute macro on impl blocks — exposes public methods to Lua.
59///
60/// For each `pub fn` with a `&self` or `&mut self` receiver, generates:
61/// 1. A static `fn(l: &mut LuaState) -> LuaResult<usize>` wrapper
62/// 2. Automatic parameter extraction from Lua stack
63/// 3. Automatic return value conversion to Lua
64///
65/// Methods are accessible from Lua via `obj:method(args)` syntax.
66///
67/// # Example
68/// ```ignore
69/// #[lua_methods]
70/// impl Point {
71/// pub fn distance(&self) -> f64 {
72/// (self.x * self.x + self.y * self.y).sqrt()
73/// }
74/// pub fn translate(&mut self, dx: f64, dy: f64) {
75/// self.x += dx;
76/// self.y += dy;
77/// }
78/// }
79/// ```
80#[proc_macro_attribute]
81pub fn lua_methods(_attr: TokenStream, input: TokenStream) -> TokenStream {
82 lua_methods::lua_methods_impl(input)
83}