capypad
0 day streak
rust / intermediate
Snippet

Newtype Pattern: Type-Safe Unit Wrappers

The newtype pattern wraps primitive types in tuple structs to create distinct types at zero runtime cost. This provides compile-time unit checking—Rust will refuse to pass Kilograms where Meters are expected. The wrapper has identical memory layout to the inner type but is treated as a completely different type by the compiler. This pattern is extensively used in physics libraries, financial applications (Money types), and anywhere type safety beyond what primitives provide is needed.

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
struct Meters(u64);
struct Seconds(u64);
struct Kilograms(u64);
 
impl Meters {
fn new(val: u64) -> Self { Meters(val) }
fn as_u64(&self) -> u64 { self.0 }
}
 
impl Seconds {
fn new(val: u64) -> Self { Seconds(val) }
fn as_u64(&self) -> u64 { self.0 }
}
 
fn calculate_speed(distance: Meters, time: Seconds) -> f64 {
if time.as_u64() == 0 { return 0.0; }
distance.as_u64() as f64 / time.as_u64() as f64
}
 
fn main() {
let distance = Meters::new(100);
let time = Seconds::new(10);
let speed = calculate_speed(distance, time);
println!("Speed: {} m/s", speed);
}
Breakdown
1
struct Meters(u64)
Tuple struct wrapping u64—completely distinct type from u64 and other wrappers
2
fn calculate_speed(distance: Meters, time: Seconds)
Function signature enforces correct units at compile time—units are part of the type