use extension_trait::extension_trait; #[extension_trait] impl Between for str { fn between(&self, front: &str, end: &str) -> Option<&str> { self.after(front).and_then(|t| t.before(end)) } fn before(&self, end: &str) -> Option<&str> { self.split(end).next() } fn after(&self, front: &str) -> Option<&str> { self.splitn(2, front).nth(1) } } #[test] fn between_works() { assert_eq!("".between("<", ">"), Some("a")); } #[test] fn before_works() { assert_eq!("".before(">"), Some("".after("a"), Some(">")); } mod x { use super::extension_trait; #[extension_trait] pub impl Public for i32 { fn method(self) -> i32 { 42 } } } #[test] fn pub_extension_trait() { use self::x::Public; assert_eq!(24i32.method(), 42); } #[extension_trait] pub impl Length for Vec { fn size(&self) -> usize { self.len() } } #[test] fn generic_extension_traits() { assert_eq!(vec!["q"].size(), 1); } #[extension_trait] pub impl ReturnArgument for () { fn return_argument(&self, arg: T) -> String where T: ToString, { arg.to_string() } } #[test] fn generic_function_extension_traits() { assert_eq!(().return_argument(42), "42"); } #[extension_trait] pub impl> DoubleBracketConversion for Vec { fn first_into_string(&self) -> String { self[0].into() } } #[test] fn double_bracket_conversion() { assert_eq!(vec!["asdf"].first_into_string(), String::from("asdf")); } #[extension_trait] pub impl DoubleBracketConversionUsingWhere for Vec where T: Copy + Into, { fn first_into_string_using_where(&self) -> String { self[0].into() } } #[test] fn double_bracket_conversion_using_where() { assert_eq!( vec!["asdf"].first_into_string_using_where(), String::from("asdf") ); } #[extension_trait] pub impl<'a, T> Unsafe for (&'a mut T, &'a mut T) { unsafe fn swap(&mut self) { std::ptr::swap(self.0, self.1) } } #[test] fn unsafe_method() { let mut a = 1; let mut b = 2; unsafe { (&mut a, &mut b).swap(); } assert_eq!(a, 2); assert_eq!(b, 1); } #[extension_trait] pub impl SliceMapExt for [T] { fn map_in_place T>(&mut self, mut f: F) { for v in self { *v = f(*v); } } } #[test] fn slice_map_ext() { let mut values = [1, 2, 3]; values.map_in_place(|x| x + 1); assert_eq!(values, [2, 3, 4]); } /// This extension trait is documented #[extension_trait] pub impl Documented for () { /// A function is documented too. fn documented(self) {} } #[test] fn documented() { assert_eq!(().documented(), ()); } #[extension_trait] impl PlusTwoReceiver for i32 { fn plus_two(mut self: Self) -> i32 { self += 2; self } } #[test] fn receiver() { assert_eq!(2.plus_two(), 4); } #[extension_trait] impl EmptyTuple for i32 { fn hi((): ()) {} } #[test] fn empty_tuple() { i32::hi(()); } #[extension_trait] impl SingleElementTuple for i32 { fn hello((r#if,): (i32,)) -> i32 { r#if } } #[test] fn single_element_tuple() { assert_eq!(i32::hello((4,)), 4); } #[extension_trait] impl Tuple for i32 { fn tuple((r#as, r#if): (i32, i32)) -> i32 { r#as + r#if } } #[test] fn two_element_tuple() { assert_eq!(i32::tuple((4, 5)), 9); } #[extension_trait] impl TupleHygiene for i32 { fn tuple_higiene((a, b): (i32, i32), a_b: i32) -> i32 { a + b + a_b } } #[test] fn tuple_higiene() { assert_eq!(i32::tuple_higiene((1, 2), 4), 7); } struct X { a: i32, b: i32, } #[extension_trait] impl StructPattern for i32 { fn x(X { a, b }: X) -> i32 { a + b } } #[test] fn struct_pattern() { assert_eq!(i32::x(X { a: 1, b: 2 }), 3); }