Derive Macro racros::CopyWith

source ·
#[derive(CopyWith)]
{
    // Attributes available to this derive:
    #[copy]
}
Expand description

Add a copy_with function for decorated type, copy value from another Self if that value is not default value.

For the following struct, generate:

struct MyStruct {
    foo1: i8,
    foo2: String,
    foo3: Option<String>,
}

impl MyStruct {
     fn copy_with(&mut self, other: &Self) {
         if other.foo1 != i8::default() {
             self.foo1 = other.foo1.clone();
         }
         if other.foo2 != String::default() {
             self.foo2 = other.foo2.clone();
         }
         if other.foo3 != Option::default() {
             self.foo3 = other.foo3.clone();
         }
     }
 }

§Usage

  • Add #[derive(CopyWith)] to struct.
  • Because types and implementations are unknown in macro expanding, add #[copy] attribute to the field which also #[derived(CopyWith)] so that will use that impl instead of default value.
  • Notice that the new value and cloned so all the fields can not be reference or borrowed type.

§Example:


use racros::CopyWith;
#[derive(Clone, Default, CopyWith)]
struct MyStruct {
    foo1: i8,
    foo2: String,
    foo3: Option<String>,
}

#[derive(CopyWith)]
struct MyStruct2 {
    #[copy]
    bar1: MyStruct,
}

let s1 = MyStruct::default();
let mut s11 = MyStruct::default();
let s2 = MyStruct {
    foo1: 64,
    foo2: String::from("hello world"),
    foo3: Some(String::from("hello world")),
};
let mut s21 = MyStruct {
    foo1: 64,
    foo2: String::from("hello world"),
    foo3: Some(String::from("hello world")),
};

s11.copy_with(&s2);
assert_eq!(s11.foo1, s2.foo1);
assert_eq!(s11.foo2, s2.foo2);
assert_eq!(s11.foo3, s2.foo3);

s21.copy_with(&s1);
assert_eq!(s21.foo1, s2.foo1);
assert_eq!(s21.foo2, s2.foo2);
assert_eq!(s21.foo3, s2.foo3);

let mut s31 = MyStruct2 {
    bar1: MyStruct::default(),
};

let s32 = MyStruct2 {
    bar1: MyStruct {
        foo1: 64,
        foo2: String::from("hello world"),
        foo3: Some(String::from("hello world")),
    },
};

s31.copy_with(&s32);
assert_eq!(s31.bar1.foo1, s2.foo1);
assert_eq!(s31.bar1.foo2, s2.foo2);
assert_eq!(s31.bar1.foo3, s2.foo3);