Skip to content

Instantly share code, notes, and snippets.

@harryscholes
Last active June 8, 2021 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harryscholes/19f1987bb751a9f823a0f4a7efa746bf to your computer and use it in GitHub Desktop.
Save harryscholes/19f1987bb751a9f823a0f4a7efa746bf to your computer and use it in GitHub Desktop.
Length traits in Rust
use std::ops::{Add, AddAssign, Mul};
#[derive(Debug)]
struct Millimeters<T>(T);
struct Centimeters<T>(Millimeters<T>);
struct Meters<T>(Millimeters<T>);
/// Length represents a length in millimeters
trait Length<T> {
fn new(x: T) -> Self;
}
impl<T> Length<T> for Millimeters<T> {
fn new(x: T) -> Millimeters<T> {
Millimeters(x)
}
}
impl<T> Length<T> for Centimeters<T>
where
T: Mul<u64, Output = T>,
{
fn new(x: T) -> Centimeters<T> {
Centimeters(Millimeters(x * 10))
}
}
impl<T> Length<T> for Meters<T>
where
T: Mul<u64, Output = T>,
{
fn new(x: T) -> Meters<T> {
Meters(Millimeters(x * 1000))
}
}
impl<T> Add for Millimeters<T>
where
T: Add<Output = T>,
{
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl<T> Add<Centimeters<T>> for Millimeters<T>
where
T: Add<Output = T>,
{
type Output = Millimeters<T>;
fn add(self, other: Centimeters<T>) -> Self::Output {
let mm = other.0;
Self(self.0 + mm.0)
}
}
impl<T> Add<Meters<T>> for Millimeters<T>
where
T: Add<Output = T>,
{
type Output = Millimeters<T>;
fn add(self, other: Meters<T>) -> Self::Output {
let mm = other.0;
Self(self.0 + mm.0)
}
}
impl<T> AddAssign for Millimeters<T>
where
T: Add<Output = T> + Copy,
{
fn add_assign(&mut self, other: Self) {
*self = Self(self.0 + other.0);
}
}
impl<T> AddAssign<Centimeters<T>> for Millimeters<T>
where
T: Add<Output = T> + Copy,
{
fn add_assign(&mut self, other: Centimeters<T>) {
let mm = other.0;
*self = Self(self.0 + mm.0);
}
}
impl<T> AddAssign<Meters<T>> for Millimeters<T>
where
T: Add<Output = T> + Copy,
{
fn add_assign(&mut self, other: Meters<T>) {
let mm = other.0;
*self = Self(self.0 + mm.0);
}
}
fn main() {
let mut d = Millimeters::new(1000);
d = d + Millimeters::new(100);
d += Centimeters::new(10);
d += Meters::new(1);
println!("{:?}", d)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment