diff --git a/src/bin/41_utility_traits.rs b/src/bin/41_utility_traits.rs index f107669..564fb94 100644 --- a/src/bin/41_utility_traits.rs +++ b/src/bin/41_utility_traits.rs @@ -8,6 +8,8 @@ // - Marker traits: traits used to expression contraits on generic types that can be caputured in any other trivial way, Size and Copy // - Public Vocabulary Trait: they are not magival to the compiler but using them mirrors convetional solutions for common problems, Default, AsRed, AsMut, Borrow and BorrowMut +use std::fmt::Debug; + fn main() { // Traits, Description // Drop: Clean up code rust runs automatically when a value is dropped @@ -129,4 +131,112 @@ fn main() { let my_box = MyBox(10); assert_eq!(10, *my_box); // *(my_box.deref()) + + #[derive(Debug)] + struct Selector { + elements: Vec, + current: usize, + } + + impl std::ops::Deref for Selector { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.elements[self.current] + } + } + + impl std::ops::DerefMut for Selector { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.elements[self.current] + } + } + + #[allow(unused_mut)] + let mut s: Selector = Selector { + elements: vec![1, 2, 3, 4], + current: 2, + }; + + assert_eq!(*s, 3); + // assert!(12i32.is_positive()); + assert!(s.is_positive()); + + // you can spell out coercion using the as keyword in rust + fn spell(number: &i32) { + println!("Spelling: {number}"); + } + + // since the spell function takes a reference to i32, we can coerce s to that + spell(&s as &i32); + #[allow(clippy::explicit_auto_deref)] + spell(&*s); //both are valid + + // Default: the default trait allows types to specify their default via a default method + impl Default for Selector { + fn default() -> Self { + Self { + elements: Vec::default(), + current: usize::default(), + } + } + } + + let default_selector = Selector::::default(); + println!("Default Selector: {default_selector:?}"); + + // all of rust collection types implement default that return empty collections + let samples = vec![2, 3, 45, 6, 23, 23, 5, 6, 34, 2, 4, 6]; + let (x_men, impure): (Vec, Vec) = samples.iter().partition(|&n| n & 1 == 0); + + println!("X-Men: {x_men:?}"); + println!("Impure: {impure:?}"); + + // if a type implements Default, then the standard library implements defaults for Arc, Rc, Box etc + + // when a type implements AsRef, it means you can borrow &T from it efficiently + // this can support some nice functionality by taking a generic type that implements a particular AsRef<> and + // then calling the as_ref method of that type to use the reference you actually want + + // for example the the std library fs open method has this signature + // std::fs::File::open; + // pub fn open

(path: P) -> io::Result + // where + // P: AsRef, + // + // in the body of the function, you really just want to get the reference to Path, so no matter what is passed in + // calling as_ref on it returns the reference to path, but this the function to allow different types + // making it look like an operator overloaded function + // + // any types U that implements the AsRef get an automatic implementation for it's &U also implementing AsRef + // this serves as a conversion trait, you should avoid defining a trait for conversion like as AsFoo, when you + // use the AsRef trait to get a reference to the Foo type for any type + + // Unlike AsRef and AsRefMut, the as From and Into take ownership of the implementor and returns a new type + /* + * trait From: Sized { + * fn from(other, T) -> Self; + * } + * + * trait Into: Sized { + * fn into(self) -> T; + * } + * + * the compiler autoimplementes the conversion of every type to itself + * for example every T implements a From and an Into + */ + + // you generally use into to make function arguments more flexible in the options they accept + /* + * use std::net::Ipv4Addr; + * fn ping(address: A) -> std::io::Result + * where A: Into + * { + * let ipv4_address = address.into(); + * ... + * } + * + * + */ + // we have TryFrom and TryInto as equivalent versions of From and Into which can fail and therefore return Result }