spread!() { /* proc-macro */ }
Expand description
Extension of the spread/struct update syntax that allow taking fields from different type structs, as long as the listed fields have the same type in both structs.
It can be used with structs that don’t have sensible defaults for each fields by using another struct that only have the fields with sensible defaults.
Fields can be listed as follows:
field,
: field which captures a variable of the same namefield: value,
: field with provided value{ field1, field2 } in source,
: fields extracted from another struct..remaining
: same as in struct update syntax, can only appear last without a trailing comma
Each field name can be prefixed by a modifier allowing to perform common transformations that usually requires repeating the field name. They are placed before the field and mean the following:
&field
: take the reference, convert aT
field to&T
&mut field
: take the mutable reference, convert aT
field to&mut T
+field
: clones the value, can be used with&source
to not consume the source>field
: converts the value withInto
+>field
: clones then converts the value withInto
, can be used with&source
to not consume the source[path] field
: pass the value to function atpath
. This path can contain module separators and turbofish. You can use this to perform custom transformations, or use more explicit alternatives to+
and>
.field
can be prefixed with&
or&mut
to pass a reference to the function instead of moving/copying it.
Here is an exemple showing all the modifers:
use spread_macros::spread;
fn to_lowercase(s: impl AsRef<str>) -> String {
s.as_ref().to_lowercase()
}
#[derive(Debug)]
struct Foo<'a> {
name: u32,
name_ref: &'a u32,
name_ref_mut: &'a mut u32,
name_into: u64,
name_clone: u32,
name_clone_into: u64,
custom: String,
value: u32,
spread: u32,
spread_ref: &'a u32,
spread_ref_mut: &'a mut u32,
spread_into: u64,
spread_clone: u32,
spread_clone_into: u64,
spread_custom: String,
other: u32,
}
#[derive(Clone, Debug, Default)]
struct Bar {
spread: u32,
spread_ref: u32,
spread_ref_mut: u32,
spread_into: u32,
spread_clone: u32,
spread_clone_into: u32,
spread_custom: String,
other: u32,
}
let mut bar = Bar::default();
let name = 42u32;
let name_ref = 42u32;
let name_into = 42u32;
let name_clone = 42u32;
let name_clone_into = 42u32;
let mut name_ref_mut = 42u32;
let custom = "HELLO WORLD";
let first = spread!(Foo {
name,
&name_ref,
&mut name_ref_mut,
>name_into,
+name_clone,
+>name_clone_into,
value: 42,
[to_lowercase] custom,
{
spread,
&spread_ref,
&mut spread_ref_mut,
>spread_into,
+spread_clone,
+>spread_clone_into,
[to_lowercase] &spread_custom,
} in &mut bar,
>other: 42u16,
});
let second = spread!(Foo {
name,
>name_into,
+name_clone,
+>name_clone_into,
value: 42,
[to_lowercase] custom,
..first
});