From 613fd638953c78e1773f26981884ed24afb9890f Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Mon, 8 Sep 2025 03:18:12 +0200 Subject: [PATCH] feat: Added derive macro to implement IntoLua on structs that implement Serialize This can be very useful if you want to convert a data struct to a lua table without having to write the boilerplane (however small it may be). It also adds the macro on several state structs so they can be converted to lua in the upcoming ActionCallback refactor. --- automation_devices/src/zigbee/light.rs | 8 ++++---- automation_devices/src/zigbee/outlet.rs | 6 +++--- automation_macro/src/lib.rs | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/automation_devices/src/zigbee/light.rs b/automation_devices/src/zigbee/light.rs index 7b5e427..dc74dda 100644 --- a/automation_devices/src/zigbee/light.rs +++ b/automation_devices/src/zigbee/light.rs @@ -10,7 +10,7 @@ use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::event::OnMqtt; use automation_lib::helpers::serialization::state_deserializer; use automation_lib::mqtt::WrappedAsyncClient; -use automation_macro::{LuaDevice, LuaDeviceConfig}; +use automation_macro::{LuaDevice, LuaDeviceConfig, LuaSerialize}; use google_home::device; use google_home::errors::ErrorCode; use google_home::traits::{Brightness, Color, ColorSetting, ColorTemperatureRange, OnOff}; @@ -40,7 +40,7 @@ pub struct Config { pub client: WrappedAsyncClient, } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, LuaSerialize)] pub struct StateOnOff { #[serde(deserialize_with = "state_deserializer")] state: bool, @@ -48,7 +48,7 @@ pub struct StateOnOff { impl LightState for StateOnOff {} -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, LuaSerialize)] pub struct StateBrightness { #[serde(deserialize_with = "state_deserializer")] state: bool, @@ -63,7 +63,7 @@ impl From for StateOnOff { } } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, LuaSerialize)] pub struct StateColorTemperature { #[serde(deserialize_with = "state_deserializer")] state: bool, diff --git a/automation_devices/src/zigbee/outlet.rs b/automation_devices/src/zigbee/outlet.rs index 47bdab6..a757595 100644 --- a/automation_devices/src/zigbee/outlet.rs +++ b/automation_devices/src/zigbee/outlet.rs @@ -10,7 +10,7 @@ use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::event::OnMqtt; use automation_lib::helpers::serialization::state_deserializer; use automation_lib::mqtt::WrappedAsyncClient; -use automation_macro::{LuaDevice, LuaDeviceConfig}; +use automation_macro::{LuaDevice, LuaDeviceConfig, LuaSerialize}; use google_home::device; use google_home::errors::ErrorCode; use google_home::traits::OnOff; @@ -57,7 +57,7 @@ pub struct Config { pub client: WrappedAsyncClient, } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, LuaSerialize)] pub struct StateOnOff { #[serde(deserialize_with = "state_deserializer")] state: bool, @@ -65,7 +65,7 @@ pub struct StateOnOff { impl OutletState for StateOnOff {} -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, LuaSerialize)] pub struct StatePower { #[serde(deserialize_with = "state_deserializer")] state: bool, diff --git a/automation_macro/src/lib.rs b/automation_macro/src/lib.rs index 17b28eb..733422c 100644 --- a/automation_macro/src/lib.rs +++ b/automation_macro/src/lib.rs @@ -3,6 +3,7 @@ mod impl_device; mod lua_device_config; use lua_device_config::impl_lua_device_config_macro; +use quote::quote; use syn::{DeriveInput, parse_macro_input}; use crate::impl_device::impl_device_macro; @@ -20,3 +21,19 @@ pub fn impl_device(input: proc_macro::TokenStream) -> proc_macro::TokenStream { impl_device_macro(&ast).into() } + +#[proc_macro_derive(LuaSerialize, attributes(traits))] +pub fn lua_serialize(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + + let name = &ast.ident; + + quote! { + impl ::mlua::IntoLua for #name { + fn into_lua(self, lua: &::mlua::Lua) -> ::mlua::Result<::mlua::Value> { + ::mlua::LuaSerdeExt::to_value(lua, &self) + } + } + } + .into() +}