diff --git a/mania-macros/src/lib.rs b/mania-macros/src/lib.rs index 582b92e..5fc5340 100644 --- a/mania-macros/src/lib.rs +++ b/mania-macros/src/lib.rs @@ -1,10 +1,12 @@ +#![feature(let_chains)] use md5::{Digest, Md5}; use proc_macro::TokenStream; -use proc_macro2::Span; +use proc_macro2::{Ident, Span}; use quote::quote; -use syn::parse::Parse; use syn::{ - DeriveInput, ItemFn, ItemStruct, LitInt, LitStr, Path, Token, parse_macro_input, + Data, DeriveInput, Fields, ItemFn, ItemStruct, LitInt, LitStr, Path, Token, + parse::{Parse, ParseStream}, + parse_macro_input, punctuated::Punctuated, }; @@ -162,13 +164,67 @@ pub fn handle_event(attr: TokenStream, item: TokenStream) -> TokenStream { expanded.into() } -// TODO: auto parse & auto impl debug -#[proc_macro_derive(ManiaEvent)] -pub fn mania_event_derive(input: TokenStream) -> TokenStream { - let ast = parse_macro_input!(input as DeriveInput); - let struct_name = &ast.ident; - let stream = quote! { +#[derive(Debug)] +struct ManiaEventPreferOptions { + debug: bool, +} + +impl Parse for ManiaEventPreferOptions { + fn parse(input: ParseStream) -> Result { + let ident: Ident = input.parse()?; + Ok(ManiaEventPreferOptions { + debug: ident == "debug", + }) + } +} + +#[proc_macro_derive(ManiaEvent, attributes(prefer))] +pub fn derive_mania_event(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as syn::DeriveInput); + let struct_name = &input.ident; + + let mania_event_impl = quote! { impl crate::event::ManiaEvent for #struct_name {} }; - stream.into() + + let debug_impl = match &input.data { + Data::Struct(data_struct) => match &data_struct.fields { + Fields::Named(fields_named) => { + let field_entries: Vec = fields_named + .named + .iter() + .map(|field| { + let field_name = field.ident.as_ref().unwrap().to_string(); + let placeholder = field + .attrs + .iter() + .find(|attr| attr.path().is_ident("prefer")) + .and_then(|attr| attr.parse_args::().ok()) + .map_or("{}", |opts| if opts.debug { "{:?}" } else { "{}" }); + format!("{}: {}", field_name, placeholder) + }) + .collect(); + let fmt_string = format!("[{}] {}", struct_name, field_entries.join(" | ")); + let field_accesses = fields_named.named.iter().map(|field| { + let field_ident = field.ident.as_ref().unwrap(); + quote! { self.#field_ident } + }); + quote! { + impl std::fmt::Debug for #struct_name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, #fmt_string, #( #field_accesses ),* ) + } + } + } + } + _ => quote! {}, + }, + _ => quote! {}, + }; + + let expanded = quote! { + #mania_event_impl + #debug_impl + }; + expanded.into() } diff --git a/mania/src/event/bot/bot_online.rs b/mania/src/event/bot/bot_online.rs index 0efe435..15b1ff6 100644 --- a/mania/src/event/bot/bot_online.rs +++ b/mania/src/event/bot/bot_online.rs @@ -1,12 +1,6 @@ -use crate::event::prelude::*; +pub use mania_macros::ManiaEvent; #[derive(ManiaEvent)] pub struct BotOnlineEvent { pub reason: String, } - -impl Debug for BotOnlineEvent { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "[BotOnlineEvent]: reason: {:?}", self.reason) - } -} diff --git a/mania/src/event/friend/friend_poke.rs b/mania/src/event/friend/friend_poke.rs index 801a121..2909685 100644 --- a/mania/src/event/friend/friend_poke.rs +++ b/mania/src/event/friend/friend_poke.rs @@ -1,4 +1,4 @@ -use crate::event::prelude::*; +pub use mania_macros::ManiaEvent; #[derive(ManiaEvent)] pub struct FriendPokeEvent { @@ -8,13 +8,3 @@ pub struct FriendPokeEvent { pub suffix: String, pub action_url: String, } - -impl Debug for FriendPokeEvent { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!( - f, - "[FriendPokeEvent]: operator_uin: {} | target_uin: {} | action: {} | suffix: {} | action_url: {}", - self.operator_uin, self.target_uin, self.action, self.suffix, self.action_url - ) - } -} diff --git a/mania/src/event/group/group_message.rs b/mania/src/event/group/group_message.rs index 04ecc7a..ecdc683 100644 --- a/mania/src/event/group/group_message.rs +++ b/mania/src/event/group/group_message.rs @@ -1,13 +1,8 @@ -use crate::event::prelude::*; use crate::message::chain::MessageChain; +pub use mania_macros::ManiaEvent; #[derive(ManiaEvent)] pub struct GroupMessageEvent { + #[prefer(debug)] pub chain: MessageChain, } - -impl Debug for GroupMessageEvent { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "[GroupMessageEvent]: {:?}", self.chain) - } -} diff --git a/mania/src/event/mod.rs b/mania/src/event/mod.rs index a5e37f4..b385806 100644 --- a/mania/src/event/mod.rs +++ b/mania/src/event/mod.rs @@ -45,8 +45,3 @@ impl EventListener { } } } - -mod prelude { - pub use mania_macros::ManiaEvent; - pub use std::fmt::{Debug, Formatter, Result as FmtResult}; -} diff --git a/mania/src/lib.rs b/mania/src/lib.rs index e75a5da..dbe438a 100644 --- a/mania/src/lib.rs +++ b/mania/src/lib.rs @@ -2,6 +2,7 @@ #![allow(dead_code)] // TODO: remove this after stable #![feature(if_let_guard)] #![feature(let_chains)] +extern crate alloc; mod core; pub mod entity;