🏗️ Reduce boilerplate
Scenario: Newtype that behaves like a number -- math operators work as any numeric type.
/// Good programmer: Strongly typed instead of Stringly typed.
pub struct HealthPoints(pub u32);
let mut me = HealthPoints(99);
let heal = HealthPoints(1);
// Want: 100 health
me.0 = me.0 + heal.0; // Not ergonomic
me = me + heal;
// me = me - heal;
// me += heal;
// me -= heal;
No macros
#![allow(unused_variables)] fn main() { use std::ops::{Add, AddAssign, Sub, SubAssign}; /// Character health points. #[derive(Clone, Copy, PartialEq)] pub struct HealthPoints(pub u32); impl Add for HealthPoints { type Output = HealthPoints; fn add(self, other: HealthPoints) -> HealthPoints { HealthPoints(self.0 + other.0) } } impl AddAssign for HealthPoints { fn add_assign(&mut self, other: HealthPoints) { *self = HealthPoints(self.0 + other.0); } } impl Sub for HealthPoints { type Output = HealthPoints; fn sub(self, other: HealthPoints) -> HealthPoints { HealthPoints(self.0 - other.0) } } impl SubAssign for HealthPoints { fn sub_assign(&mut self, other: HealthPoints) { *self = HealthPoints(self.0 - other.0); } } }
Reduction level 1 -- `proc_macro_derive`
/// Character health points.
#[derive(
derive_more::Add,
derive_more::AddAssign,
derive_more::Sub,
derive_more::SubAssign,
derive_more::Display,
derive_more::From,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
)]
pub struct HealthPoints(pub u32);
/// Character skill points.
#[derive(
derive_more::Add,
derive_more::AddAssign,
derive_more::Sub,
derive_more::SubAssign,
derive_more::Display,
derive_more::From,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
)]
pub struct SkillPoints(pub u32);
Reduction level 2 -- `proc_macro_attribute`
use numeric_newtype_derive::numeric_newtype;
/// Character health points.
#[numeric_newtype]
pub struct HealthPoints(pub u32);
/// Character skill points.
#[numeric_newtype]
pub struct SkillPoints(pub u32);