use enum_delegate::delegate; trait Name {} impl Name for String {} #[delegate] trait Named where N: Name, { fn name(&self) -> N; } #[delegate] trait Versioned { fn version(&self) -> String; } // TODO: Add generics to `Named` and `Versioned`, once assertion, that derive // actually implements trait is added. #[delegate(derive(Named, Versioned))] enum Users { Oleg(UserOleg), Boris { user: UserBoris }, } struct UserOleg(String); impl Named for UserOleg { fn name(&self) -> String { self.0.clone() } } impl Versioned<2> for UserOleg { fn version(&self) -> String { format!("UserOleg v2") } } struct UserBoris { name: String, } impl Named for UserBoris { fn name(&self) -> String { self.name.clone() } } impl Versioned<2> for UserBoris { fn version(&self) -> String { format!("UserBoris v2") } } #[test] fn derives_with_generics() { let oleg = Users::Oleg(UserOleg("Oleg".to_string())); assert_eq!(oleg.name(), "Oleg"); let boris = Users::Boris { user: UserBoris { name: "Boris".to_string(), }, }; assert_eq!(boris.name(), "Boris"); } #[test] fn derives_with_const_generics() { let oleg = Users::Oleg(UserOleg("Oleg".to_string())); assert_eq!(oleg.version(), "UserOleg v2"); let boris = Users::Boris { user: UserBoris { name: "Boris".to_string(), }, }; assert_eq!(boris.version(), "UserBoris v2"); }