use penrose_proc::stubbed_companion_trait; #[derive(Debug, Eq, PartialEq)] enum Animal { Cat, Dog, } #[stubbed_companion_trait] trait Colors { #[stub("red")] fn color(&self, x: u32) -> &str; } #[stubbed_companion_trait] trait AnimalsAndColors: Colors { #[stub(Some(Animal::Cat))] fn animal(&self, name: &str) -> Option; fn best_animal(&self) -> Animal { Animal::Dog } fn colored_animal(&self, name: &str, x: u32) -> String { if let Some(a) = self.animal(name) { let color = self.color(x); format!("A {:?} that is {}", a, color) } else { format!("Not sure what a {} is", name) } } } struct ImplColors; impl Colors for ImplColors { fn color(&self, x: u32) -> &str { match x { 42 => "red", _ => "green", } } } #[test] fn it_is_possible_to_impl_the_original_trait() { let ic = ImplColors; assert_eq!(ic.color(42), "red"); assert_eq!(ic.color(19), "green"); } struct DeriveStubbedAnimalsAndColors; impl StubColors for DeriveStubbedAnimalsAndColors {} impl StubAnimalsAndColors for DeriveStubbedAnimalsAndColors {} #[test] fn default_method_impls_are_copied() { let d = DeriveStubbedAnimalsAndColors; assert_eq!(d.best_animal(), Animal::Dog); } #[test] fn trait_bounds_are_maintained() { let d = DeriveStubbedAnimalsAndColors; assert_eq!(&d.colored_animal("anything", 42), "A Cat that is red"); } // ----- mod inner { #[penrose_proc::stubbed_companion_trait] pub trait InnerColors { #[stub("blue")] fn color(&self, x: u32) -> &str; } } use inner::InnerColors; struct OuterImplementer; impl inner::StubInnerColors for OuterImplementer {} #[test] fn visibility_of_stubs_matches_original() { let o = OuterImplementer; assert_eq!(o.color(42), "blue"); } // ----- #[allow(dead_code)] #[derive(Eq, PartialEq, Debug)] enum Scale { Major, Minor, Blues, } #[stubbed_companion_trait(prefix = "CustomPrefix")] trait Musical { #[stub("F#")] fn musical_note(&self, x: u32) -> &str; #[stub(Scale::Blues)] fn musical_scale(&self, f: f64) -> Scale; } struct ImplMusical; impl CustomPrefixMusical for ImplMusical {} #[test] fn custom_prefix_works() { let i = ImplMusical; assert_eq!(i.musical_note(17), "F#"); assert_eq!(i.musical_scale(3.0), Scale::Blues); } // -----