-
Notifications
You must be signed in to change notification settings - Fork 310
Open
Description
Feature Request
currently, when users want to use EXT, because we need to handle Any
, some fixed code
has to be implemented manually by users.
Here is a demo, and as_any
and fory_default
are some fixed code.
#[derive(Debug, PartialEq, Default)]
struct ExtItem {
id: i32,
}
impl ForyDefault for ExtItem {
fn fory_default() -> Self {
Self::default()
}
}
impl Serializer for ExtItem {
fn fory_write_data(&self, context: &mut WriteContext, is_field: bool) {
write_data(&self.id, context, is_field);
}
fn fory_read_data(context: &mut ReadContext, is_field: bool) -> Result<Self, Error> {
Ok(Self {
id: read_data(context, is_field)?,
})
}
fn fory_type_id_dyn(&self, fory: &Fory) -> u32 {
Self::fory_get_type_id(fory)
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
This is inconvenient. But now I haven't find how to set default implementation for as_any
before runtime. And impl ForyDefault
must be implemented manually. If all else cannot work, we can give users a helper macro.
Describe the solution you'd like
Here is a helper macro implementation.
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemImpl};
#[proc_macro_attribute]
pub fn ext_helper(_attr: TokenStream, item: TokenStream) -> TokenStream {
// 解析原来的 impl 块
let input = parse_macro_input!(item as ItemImpl);
let self_ty = &input.self_ty;
let mut new_items = input.items.clone();
// 内部插入函数 as_any
let injected_inside = syn::parse_quote! {
fn as_any(&self) -> &dyn std::any::Any {
self
}
};
new_items.push(injected_inside);
// 生成原 impl + 内部注入函数
let original_impl = ItemImpl {
items: new_items,
..input.clone()
};
// 生成 impl ForyDefault for <Type>
let fory_default_impl = quote! {
impl ForyDefault for #self_ty {
fn fory_default() -> Self {
Self::default()
}
}
};
let expanded = quote! {
#original_impl
#fory_default_impl
};
TokenStream::from(expanded)
}
and use it as:
use my_macro::ext_helper;
trait Serializer {
fn serialize(&self);
}
struct Foo;
#[ext_helper]
impl Serializer for Foo {
fn serialize(&self) {}
}
fn main() {
}
the expanded code is:
use my_macro::ext_helper;
trait Serializer {
fn serialize(&self);
}
struct Foo;
impl Serializer for Foo {
fn serialize(&self) {}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl ForyDefault for Foo {
fn fory_default() -> Self {
Self::default()
}
}
fn main() {}
Metadata
Metadata
Assignees
Labels
No labels