Skip to content

Commit

Permalink
Allow specification of lifetimes in mapping macros (#6)
Browse files Browse the repository at this point in the history
* Lifetime tweaks

* Clean up and add test
  • Loading branch information
michaelsproul authored Nov 12, 2024
1 parent 79dc75c commit 54b12d2
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ members = [
"metastruct",
"metastruct_macro",
]
resolver = "2"
15 changes: 9 additions & 6 deletions metastruct_macro/src/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ pub(crate) fn generate_mapping_macro(
quote! { ref }
};

let mapping_function_types = selected_field_types
let mapping_function_input_types = selected_field_types
.iter()
.map(|field_type| {
if mapping_opts.mutable {
quote! { &mut dyn FnMut(usize, &'_ mut #field_type) -> _ }
quote! { mut #field_type }
} else {
quote! { &mut dyn FnMut(usize, &'_ #field_type) -> _ }
quote! { #field_type }
}
})
.collect::<Vec<_>>();
Expand All @@ -54,7 +54,7 @@ pub(crate) fn generate_mapping_macro(
quote! {
#[macro_export]
macro_rules! #macro_name {
($v:expr, $f:expr) => {
(&$lifetime:tt _, $v:expr, $f:expr) => {
match $v {
#type_name {
#(
Expand All @@ -64,13 +64,16 @@ pub(crate) fn generate_mapping_macro(
} => {
let mut __metastruct_i: usize = 0;
#(
let __metastruct_f: #mapping_function_types = &mut $f;
let __metastruct_f: &mut dyn FnMut(usize, &$lifetime #mapping_function_input_types) -> _ = &mut $f;
#function_call_exprs;
__metastruct_i += 1;
)*
}
}
}
};
($v:expr, $f:expr) => {
#macro_name!(&'_ _, $v, $f)
};
}
}
.into()
Expand Down
20 changes: 20 additions & 0 deletions metastruct_macro/tests/lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use metastruct_macro::metastruct;

#[metastruct(mappings(map_foo_fields()))]
struct Foo {
x: u64,
y: u16,
z: u32,
}

fn sum<'a>(total: &'a mut u64, foo: &'a Foo) {
map_foo_fields!(&'a _, foo, |_, field| *total += *field as u64);
}

#[test]
fn reference_with_lifetime() {
let foo = Foo { x: 1, y: 2, z: 3 };
let mut total = 0;
sum(&mut total, &foo);
assert_eq!(total, 6);
}

0 comments on commit 54b12d2

Please sign in to comment.