use enum_delegate::delegate; #[delegate] trait User { fn name(&'_ self) -> &'_ str; fn prepended_with_name(&'_ self, s: &'_ str) -> String; fn prepend_with_name<'s>(&'s self, s: &'s mut String) -> &'s mut String; fn prepend_name_to<'s>(&self, s: &'s mut String); fn into_prepended_with_name<'a>(self, s: &'a str) -> String; } struct UserOleg; impl User for UserOleg { fn name(&'_ self) -> &'_ str { "Oleg" } fn prepended_with_name(&'_ self, s: &'_ str) -> String { format!("{}'s {s}", self.name()) } fn prepend_with_name<'s>(&self, s: &'s mut String) -> &'s mut String { s.insert_str(0, &format!("{}'s ", self.name())); s } fn prepend_name_to(&self, s: &mut String) { s.insert_str(0, &format!("{}'s ", self.name())); } fn into_prepended_with_name<'a>(self, s: &'a str) -> String { format!("{}'s {s}", self.name()) } } struct UserBoris; impl User for UserBoris { fn name(&'_ self) -> &'_ str { "Boris" } fn prepended_with_name(&'_ self, s: &'_ str) -> String { format!("{}'s {s}", self.name()) } fn prepend_with_name<'s>(&self, s: &'s mut String) -> &'s mut String { s.insert_str(0, &format!("{}'s ", self.name())); s } fn prepend_name_to(&self, s: &mut String) { s.insert_str(0, &format!("{}'s ", self.name())); } fn into_prepended_with_name<'a>(self, s: &'a str) -> String { format!("{}'s {s}", self.name()) } } // TODO: Add generics to `User` once assertion, that derive actually // implements trait is added. #[delegate(derive(User))] enum Users { Oleg(UserOleg), Boris(UserBoris), } #[test] fn derives_with_lifetimes() { let oleg = Users::Oleg(UserOleg); assert_eq!(oleg.name(), "Oleg"); assert_eq!(oleg.prepended_with_name("apple"), "Oleg's apple"); assert_eq!( oleg.prepend_with_name(&mut String::from("orange")), "Oleg's orange", ); let mut orange = String::from("orange"); oleg.prepend_name_to(&mut orange); assert_eq!(orange, "Oleg's orange"); assert_eq!(oleg.into_prepended_with_name("apple"), "Oleg's apple"); let boris = Users::Boris(UserBoris); assert_eq!(boris.name(), "Boris"); assert_eq!(boris.prepended_with_name("apple"), "Boris's apple"); assert_eq!( boris.prepend_with_name(&mut String::from("orange")), "Boris's orange", ); let mut orange = String::from("orange"); boris.prepend_name_to(&mut orange); assert_eq!(orange, "Boris's orange"); assert_eq!(boris.into_prepended_with_name("apple"), "Boris's apple"); }