diff --git a/Cargo.toml b/Cargo.toml index 00569a38e..7da8b7587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "iceoryx2-bb/lock-free/", "iceoryx2-bb/threadsafe/", "iceoryx2-bb/container", + "iceoryx2-bb/derive-macros", "iceoryx2-bb/elementary", "iceoryx2-bb/log", "iceoryx2-bb/memory", @@ -40,6 +41,7 @@ version = "0.3.0" iceoryx2-bb-threadsafe = { version = "0.3.0", path = "iceoryx2-bb/threadsafe/" } iceoryx2-bb-lock-free = { version = "0.3.0", path = "iceoryx2-bb/lock-free/" } iceoryx2-bb-container = { version = "0.3.0", path = "iceoryx2-bb/container/" } +iceoryx2-bb-derive-macros = { version = "0.3.0", path = "iceoryx2-bb/derive-macros/" } iceoryx2-bb-elementary = { version = "0.3.0", path = "iceoryx2-bb/elementary/" } iceoryx2-bb-log = { version = "0.3.0", path = "iceoryx2-bb/log/" } iceoryx2-bb-memory = { version = "0.3.0", path = "iceoryx2-bb/memory/" } @@ -68,8 +70,11 @@ log = { version = "0.4.21" } once_cell = { version = "1.19.0" } ouroboros = { version = "0.18.4" } pin-init = { version = "0.2.0" } +proc-macro2 = { version = "1.0.84" } +quote = { version = "1.0.36" } serde = { version = "1.0.203", features = ["derive"] } sha1_smol = { version = "1.0.0" } +syn = { version = "2.0.66", features = ["full"] } termsize = { version = "0.1.6" } tiny-fn = { version = "0.1.5" } toml = { version = "0.8.13" } diff --git a/iceoryx2-bb/derive-macros/Cargo.toml b/iceoryx2-bb/derive-macros/Cargo.toml new file mode 100644 index 000000000..114a45468 --- /dev/null +++ b/iceoryx2-bb/derive-macros/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "iceoryx2-bb-derive-macros" +categories = { workspace = true } +description = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +keywords = { workspace = true } +license = { workspace = true } +readme = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = { workspace = true } +quote = { workspace = true } +syn = { workspace = true } +iceoryx2-bb-elementary = { workspace = true } diff --git a/iceoryx2-bb/derive-macros/src/lib.rs b/iceoryx2-bb/derive-macros/src/lib.rs new file mode 100644 index 000000000..96f0a4b2f --- /dev/null +++ b/iceoryx2-bb/derive-macros/src/lib.rs @@ -0,0 +1,41 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, Data, DeriveInput, Fields}; + +#[proc_macro_derive(PlacementDefault)] +pub fn placement_default_derive(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = &input.ident; + + let place_new_impl = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Named(ref fields_named) => { + let field_inits = fields_named.named.iter().map(|f| { + let field_type = &f.ty; + let name = &f.ident; + quote! { + #field_type::placement_default(&mut (*ptr).#name); + } + }); + + quote! { + unsafe fn placement_default(ptr: *mut #name) { + #(#field_inits)* + } + } + } + _ => unimplemented!(), + }, + _ => unimplemented!(), + }; + + let expanded = quote! { + impl iceoryx2_bb_elementary::placement_new::PlacementDefault for #name { + #place_new_impl + } + }; + + TokenStream::from(expanded) +} diff --git a/iceoryx2-bb/trait-tests/Cargo.toml b/iceoryx2-bb/trait-tests/Cargo.toml index b3adc41ad..3091054f2 100644 --- a/iceoryx2-bb/trait-tests/Cargo.toml +++ b/iceoryx2-bb/trait-tests/Cargo.toml @@ -14,6 +14,7 @@ version = { workspace = true } [dev-dependencies] iceoryx2-bb-container = { workspace = true } +iceoryx2-bb-derive-macros = { workspace = true } iceoryx2-bb-elementary = { workspace = true } iceoryx2-bb-memory = { workspace = true } iceoryx2-bb-lock-free = { workspace = true } diff --git a/iceoryx2-bb/trait-tests/tests/placement_new_tests.rs b/iceoryx2-bb/trait-tests/tests/placement_new_tests.rs new file mode 100644 index 000000000..749fb30f4 --- /dev/null +++ b/iceoryx2-bb/trait-tests/tests/placement_new_tests.rs @@ -0,0 +1,23 @@ +#[cfg(test)] +mod placement_new { + use std::alloc::{alloc, dealloc, Layout}; + + use iceoryx2_bb_derive_macros::PlacementDefault; + use iceoryx2_bb_elementary::placement_new::PlacementDefault; + + #[derive(Default, PlacementDefault)] + struct TestStruct { + a: i32, + b: u64, + } + + #[test] + fn whatever() { + let layout = Layout::new::(); + let memory = unsafe { alloc(layout) } as *mut TestStruct; + let sut = TestStruct::default(); + unsafe { TestStruct::placement_default(memory) }; + + unsafe { dealloc(memory.cast(), layout) }; + } +}