Skip to content

Instantly share code, notes, and snippets.

@uvicorn
Last active February 2, 2024 17:43
Show Gist options
  • Save uvicorn/0bd4cf624944709c3cb8193aca9ad529 to your computer and use it in GitHub Desktop.
Save uvicorn/0bd4cf624944709c3cb8193aca9ad529 to your computer and use it in GitHub Desktop.
Add fields\functions to struct && add implementations of functions in the implementation of a trait by a structure
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemImpl};
#[proc_macro_attribute]
pub fn DefaultTraitImpl(args: TokenStream, input: TokenStream) -> TokenStream {
let ii= parse_macro_input!(input as ItemImpl);
let a = &ii.attrs; // avtor dolboyoba, ne obrazhiaite vnimanii
let u = &ii.unsafety;
let s = &ii.self_ty;
let (ba, pa, fo) = ii.trait_.unwrap(); // bang, path, for tokens
let g = &ii.generics;
let i = &ii.impl_token;
let it = &ii.items;
let d = &ii.defaultness;
return quote! {
#(#a)*
#d #u #i #g #ba #pa #fo #s { // default unsafe impl<'a, T> ! MyTrait for User
#(#it)*
fn get_id(&self) -> i8{
1
}
}
}
.into();
}
/*
trait MyTrait {
fn get_id(&self) -> i8;
fn new_i8() -> i8;
}
struct User{}
#[DefaultTraitImpl]
impl MyTrait for User {
fn new_i8() -> i8 {
2
}
}
let user = User {};
println!("{}", user.get_id()); // 1
*/
use proc_macro::TokenStream;
use quote::quote;
use syn::parse::Parser;
use syn::{parse, parse_macro_input, ItemStruct};
use proc_macro2::{Ident, Span};
use syn::parse::Parser;
#[proc_macro_attribute]
pub fn BaseObject(args: TokenStream, input: TokenStream) -> TokenStream {
let mut item_struct = parse_macro_input!(input as ItemStruct);
let _ = parse_macro_input!(args as parse::Nothing);
let fields_to_add = vec![quote!{field: i8 }]; // Insert quote!{ Field: Type }
let name = &item_struct.ident;
if let syn::Fields::Named(ref mut fields) = item_struct.fields {
for f in fields_to_add{
fields.named.push(
syn::Field::parse_named
.parse2(f)
.unwrap(),
);
}
}
let name_low = Ident::new(&(name.to_string().to_lowercase())[..], Span::call_site()); // example of creating Ident
return quote! {
#item_struct
impl #name {
pub fn print_field(&self) {
println!("Struct {} has field equal to {}", #name_low , self.field; // println!("#name_low") will print #name_low, not its value
}
}
}
.into();
}
/*
#[BaseObject]
struct MyStruct {
new_field: i16
}
let my = MyStruct { field: 1, field16: 2};
my.print_field(); // Struct mystruct has field equal to 1
*/
[package]
name = "libmacro"
version = "0.1.0"
edition = "2018"
publish = false
[lib]
proc-macro = true
[dependencies]
syn = { version = "1.0", features = ["full"] }
quote = "1.0"
proc-macro2 = "1.0"
macroquad = "0.3"
@Jomy10
Copy link

Jomy10 commented Jan 7, 2022

After a lot of searching, finally found a working macro example to add a field to a struct, thank you for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment