Skip to content

Commit 712e4ba

Browse files
author
Brian Obot
committed
Add notes on Deref Trait
1 parent 9da6c53 commit 712e4ba

1 file changed

Lines changed: 94 additions & 1 deletion

File tree

src/bin/41_utility_traits.rs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
#![allow(dead_code, unused_variables)]
2+
3+
// you can think of utility trait as a bunch of traits in the standrd library that has alot of impact on the way Rust is wrriten
4+
// mastering them would make one write more idiomatic code and build crates public interfaces better
5+
6+
// broading speaking, there are categorized into following sets
7+
// - Language extension traits: like the operator overloading traits, Drop traits, Deref, DerefMut and conversion trait
8+
// - Marker traits: traits used to expression contraits on generic types that can be caputured in any other trivial way, Size and Copy
9+
// - 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
10+
111
fn main() {
212
// Traits, Description
313
// Drop: Clean up code rust runs automatically when a value is dropped
@@ -14,26 +24,109 @@ fn main() {
1424
// Drop
1525
// you can customize how run process dropping of types by implementing Drop for your type
1626

27+
let mut names = vec![1, 2, 3, 4, 5];
28+
println!("Capacity: {}", names.capacity());
29+
println!("Length: {}", names.len());
30+
31+
names.truncate(4);
32+
println!("After Truncation");
33+
println!("Capacity: {}", names.capacity());
34+
println!("Length: {}", names.len());
35+
1736
#[derive(Debug)]
1837
struct Person {
1938
name: String,
2039
}
2140

2241
impl Drop for Person {
2342
fn drop(&mut self) {
24-
println!("Dropping Person")
43+
println!("Dropping Person: Name = {}", self.name);
44+
// because the drop method on a value is called, before the value is actually drop
45+
// the value is still fully initialized and all it's field can still be used
2546
}
2647
}
2748

2849
let brian = Person {
2950
name: "Brian".to_string(),
3051
};
52+
println!("✅ Start of Section on Drop Trait");
3153
println!("brian: {brian:?}");
3254
println!("person name: {:?}", brian.name);
3355
// rust calls the drop trait of a type if it implement the Drop trait
3456
// and then after that drops the value, so the value is not dropped in the drop
3557
// method of the Drop trait but some other logic can happen there
58+
//
59+
{
60+
let mut _person = Person {
61+
name: "Albert".to_string(),
62+
};
63+
println!("Before Assignment");
64+
65+
_person = Person {
66+
name: "James".to_string(),
67+
};
68+
println!("At the end of the block");
69+
}
70+
71+
println!("✅ End of Section on Drop Trait");
3672

3773
// if a variable value is moved into another variable, when the variable goes out of scope
3874
// rust will not try to drop it, since it does not contain any value
75+
// if a type implement Drop it can not implement Copy and vice versa
76+
77+
// Sized: is a type whose values have the same size in memory
78+
// all sized types implement the Sized marker trait which has no methods or associated types
79+
// you can not implement it yourself, the only need of the Size trait is as a trait bound for types that implement it
80+
//
81+
// rust can not store unsized values in variables or pass them around
82+
// that why you must interact with them through pointers, like & and Box
83+
// a pointer to a unsize value is always a fat pointer, a pointer to the item in the head and the length
84+
let information = "Some Information that might be important for the next learner";
85+
86+
// all generics types are implicitly Sized
87+
// when you write fn gen<T>() {} rust treats T as fn gen<T: Size>() {}
88+
//
89+
// Clone: Clone must be infalliable
90+
// Copy: these are the exception to the moving values rule of rust, since the types that implement this
91+
// are simple and do not have resources, the are simply Copied, a Copy is an subtrait of the Clone trait
92+
93+
trait Copy: Clone {} // it is a marker trait
94+
// types that own resources like heap buffers or operating system handles can not implement copy
95+
// likewise any type that implement the Drop trait can not implement Copy
96+
//
97+
// Deref and DerefMut: this specifies how Rust handles the dereferencing operators like * and .
98+
// let b = Box<Complex> implements Deref and DerefMut, so *b refers to Complex, and b.re refers to the real part of Complex
99+
100+
#[allow(dead_code)]
101+
trait Deref {
102+
type Target: ?Sized;
103+
104+
fn deref(&self) -> &Self::Target;
105+
}
106+
107+
#[allow(dead_code)]
108+
trait DerefMut: Deref {
109+
fn deref_mut(&mut self) -> &mut Self::Target;
110+
}
111+
112+
// Target should be something that Self Contains, owns or refer to
113+
let underlying_value = 5;
114+
let door = &underlying_value;
115+
let opened_door = *door;
116+
117+
assert_eq!(5, underlying_value);
118+
assert_eq!(5, opened_door);
119+
120+
struct MyBox<T>(T);
121+
122+
impl<T> std::ops::Deref for MyBox<T> {
123+
type Target = T;
124+
125+
fn deref(&self) -> &Self::Target {
126+
&self.0
127+
}
128+
}
129+
130+
let my_box = MyBox(10);
131+
assert_eq!(10, *my_box); // *(my_box.deref())
39132
}

0 commit comments

Comments
 (0)