Add custom macro for ReprC impl
This commit is contained in:
parent
f34f5974ac
commit
b5af5fbe70
6 changed files with 118 additions and 0 deletions
|
@ -10,6 +10,7 @@ rand = "0.8.5"
|
||||||
backtrace = "0.3.67"
|
backtrace = "0.3.67"
|
||||||
assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
assetpath = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
|
reprc_proc_macro = { path = "src/reprc_proc_macro" }
|
||||||
|
|
||||||
# networking
|
# networking
|
||||||
serde = { version = "1.0.152", features = ["derive"] }
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
|
|
|
@ -14,4 +14,7 @@ pub mod try_lock_guard;
|
||||||
pub mod arc_unique_vec;
|
pub mod arc_unique_vec;
|
||||||
pub mod rc_unique_vec;
|
pub mod rc_unique_vec;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod repr_c;
|
||||||
|
|
||||||
pub mod unsafe_life_time;
|
pub mod unsafe_life_time;
|
||||||
|
|
|
@ -27,3 +27,6 @@ pub use crate::try_lock_guard::TryLockGuard;
|
||||||
|
|
||||||
// unsafe life time trickery
|
// unsafe life time trickery
|
||||||
pub use crate::unsafe_life_time::*;
|
pub use crate::unsafe_life_time::*;
|
||||||
|
|
||||||
|
pub use crate::repr_c::ReprC;
|
||||||
|
pub use reprc_proc_macro::DeriveReprC;
|
||||||
|
|
36
src/repr_c.rs
Normal file
36
src/repr_c.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use reprc_proc_macro::DeriveReprC;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_reprc {
|
||||||
|
(
|
||||||
|
$(#[$meta: meta])*
|
||||||
|
$v:vis struct $struct_name:ident {
|
||||||
|
$( $(#[$field_meta:meta])* $member:ident : $t:ty, )+
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, DeriveReprC)]
|
||||||
|
$(#[$meta])*
|
||||||
|
$v struct $struct_name {
|
||||||
|
$(
|
||||||
|
$( #[$field_meta] )*
|
||||||
|
pub $member: $t,
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_reprc!(
|
||||||
|
struct Test {
|
||||||
|
#[assume_reprc]
|
||||||
|
i1: i32,
|
||||||
|
#[assume_reprc]
|
||||||
|
i2: i32,
|
||||||
|
#[assume_reprc]
|
||||||
|
v1: Vec<i32>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
pub unsafe trait ReprC {
|
||||||
|
fn is_repr_c(&self) -> bool;
|
||||||
|
}
|
13
src/reprc_proc_macro/Cargo.toml
Normal file
13
src/reprc_proc_macro/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "reprc_proc_macro"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = { version = "1.0.107", features = ["full", "fold"] }
|
||||||
|
quote = "1.0.23"
|
62
src/reprc_proc_macro/src/lib.rs
Normal file
62
src/reprc_proc_macro/src/lib.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{quote, ToTokens};
|
||||||
|
use syn::{parse_macro_input, Data, DeriveInput, Ident};
|
||||||
|
|
||||||
|
const REPRC_ATTRIBUTE: &'static str = "assume_reprc";
|
||||||
|
|
||||||
|
#[proc_macro_derive(DeriveReprC, attributes(assume_reprc))]
|
||||||
|
pub fn reprc_builder(item: TokenStream) -> TokenStream {
|
||||||
|
let ast = parse_macro_input!(item as DeriveInput);
|
||||||
|
|
||||||
|
let struct_name = ast.ident;
|
||||||
|
let generics = ast.generics.to_token_stream();
|
||||||
|
|
||||||
|
match ast.data {
|
||||||
|
Data::Struct(data_struct) => match data_struct.fields {
|
||||||
|
syn::Fields::Named(named_fields) => {
|
||||||
|
let reprc_fields: Vec<Ident> = named_fields
|
||||||
|
.named
|
||||||
|
.iter()
|
||||||
|
.filter_map(|field| {
|
||||||
|
if field
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.find(|attribute| {
|
||||||
|
let segments = &attribute.path.segments;
|
||||||
|
|
||||||
|
if segments.len() < 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
segments[0].ident == REPRC_ATTRIBUTE
|
||||||
|
})
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(field.ident.clone())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|i| i.unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
unsafe impl #generics ReprC for #struct_name #generics {
|
||||||
|
fn is_repr_c(&self) -> bool {
|
||||||
|
true
|
||||||
|
|
||||||
|
#(
|
||||||
|
&& self. #reprc_fields.to_tokens() .is_repr_c()
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
syn::Fields::Unnamed(_) => todo!("Unnamed Field not supported"),
|
||||||
|
syn::Fields::Unit => todo!("Unit not supported"),
|
||||||
|
},
|
||||||
|
|
||||||
|
Data::Enum(_) => todo!("Enum not supported"),
|
||||||
|
Data::Union(_) => todo!("Union not supported"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue