use core::convert::TryInto; use enum_dispatch::enum_dispatch; #[enum_dispatch(Traited1)] #[enum_dispatch(Traited2)] trait Trait { fn describe(&self) -> char; } impl Trait for A { fn describe(&self) -> char { 'A' } } impl Trait for B { fn describe(&self) -> char { 'B' } } impl Trait for C { fn describe(&self) -> char { 'C' } } #[enum_dispatch(Traited1, Traited2)] trait TraitSingleLine { fn as_string(&self) -> String; } impl TraitSingleLine for A { fn as_string(&self) -> String { "A".to_string() } } impl TraitSingleLine for B { fn as_string(&self) -> String { " B ".to_string() } } impl TraitSingleLine for C { fn as_string(&self) -> String { self.describe().to_string() } } pub struct A; pub struct B; pub struct C; #[enum_dispatch] pub enum Traited1 { A, B, C, } #[enum_dispatch] pub enum Traited2 { A, B, C, } #[test] fn main() { let a = Traited1::from(A); let b = Traited1::from(B); let c = Traited1::from(C); assert_eq!(a.describe(), 'A'); assert_eq!(b.describe(), 'B'); assert_eq!(c.describe(), 'C'); assert_eq!(a.as_string(), "A".to_string()); assert_eq!(b.as_string(), " B ".to_string()); assert_eq!(c.as_string(), "C".to_string()); let b_from_c: Result = c.try_into(); assert!(b_from_c.is_err()); assert_eq!(b_from_c.err().unwrap(), "Tried to convert variant C to B"); let a_from_a: Result = a.try_into(); assert!(a_from_a.is_ok()); let a_sl = Traited2::from(A); let b_sl = Traited2::from(B); let c_sl = Traited2::from(C); assert_eq!(a_sl.describe(), 'A'); assert_eq!(b_sl.describe(), 'B'); assert_eq!(c_sl.describe(), 'C'); assert_eq!(a_sl.as_string(), "A".to_string()); assert_eq!(b_sl.as_string(), " B ".to_string()); assert_eq!(c_sl.as_string(), "C".to_string()); let b_from_c_sl: Result = c_sl.try_into(); assert!(b_from_c_sl.is_err()); assert_eq!( b_from_c_sl.err().unwrap(), "Tried to convert variant C to B" ); let a_from_a_sl: Result = a_sl.try_into(); assert!(a_from_a_sl.is_ok()); }