capypad
0 day streak
rust / intermediate
Snippet

Implementing Standard Traits: Default, Clone, and From

Implementing standard library traits allows your types to integrate seamlessly with Rust's ecosystem. The Default trait provides a fallback value when no specific data is needed. Clone trait (deriveable) creates a deep copy of your data. From and Into traits enable conversion between types - when you implement From for a type, Into is automatically available. This pattern is idiomatic Rust: instead of having multiple constructors, you implement general-purpose traits that compose well with the standard library. For example, many collection methods expect types that implement From or Into.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#[derive(Debug, Clone)]
struct Point {
x: f64,
y: f64,
}
 
#[derive(Debug)]
struct Line {
start: Point,
end: Point,
}
 
impl Default for Line {
fn default() -> Self {
Self {
start: Point { x: 0.0, y: 0.0 },
end: Point { x: 1.0, y: 1.0 },
}
}
}
 
impl From<(f64, f64)> for Point {
fn from(coords: (f64, f64)) -> Self {
Point { x: coords.0, y: coords.1 }
}
}
 
impl From<Point> for (f64, f64) {
fn from(point: Point) -> Self {
(point.x, point.y)
}
}
 
impl Line {
fn new(start: Point, end: Point) -> Self {
Self { start, end }
}
 
fn length(&self) -> f64 {
let dx = self.end.x - self.start.x;
let dy = self.end.y - self.start.y;
(dx * dx + dy * dy).sqrt()
}
}
 
fn main() {
let default_line = Line::default();
println!("Default line: {:?}", default_line);
 
let point_from_tuple: Point = (3.0, 4.0).into();
println!("Point from tuple: {:?}", point_from_tuple);
 
let tuple_from_point: (f64, f64) = point_from_tuple.into();
println!("Tuple from point: {:?}", tuple_from_point);
 
let line = Line::new((0.0, 0.0).into(), (3.0, 4.0).into());
println!("Line length: {:.2}", line.length());
}
Breakdown
1
#[derive(Debug, Clone)]
Derive Debug for printing and Clone for creating copies of Point
2
struct Point { x: f64, y: f64 }
Simple 2D point structure with floating-point coordinates
3
impl Default for Line {
Manually implement Default for Line since it contains non-Default fields
4
fn default() -> Self {
Return a Line with default unit diagonal from (0,0) to (1,1)
5
impl From<(f64, f64)> for Point {
Implement conversion FROM tuple TO Point
6
impl From<Point> for (f64, f64) {
Implement conversion FROM Point TO tuple (reverse direction)
7
fn main() {
Demonstrate the traits in action
8
Line::default()
Creates a Line using the Default implementation
9
Point::from((3.0, 4.0))
Convert tuple (3.0, 4.0) to Point using From trait
10
let tuple_from_point: (f64, f64) = point.into();
Convert Point back to tuple using the reverse From implementation
11
Line::new((0.0, 0.0).into(), (3.0, 4.0).into())
Chain .into() calls to create a Line from tuples directly