rustyfi_backend/
length.rs1use newer_type::implement;
2use std::ops::{Add, Div, Mul, Neg, Sub};
3
4#[implement(newer_type_std::ops::AddAssign)]
14#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
15pub struct Length(pub f64);
16
17impl Length {
18 pub const ZERO: Length = Length(0.0);
19
20 pub const fn pt(v: f64) -> Length {
21 Length(v)
22 }
23
24 pub fn from_unit(value: f64, unit: &str) -> Option<Length> {
26 let pt = match unit {
27 "pt" => value,
28 "mm" => value * 72.0 / 25.4,
29 "cm" => value * 72.0 / 2.54,
30 "inch" => value * 72.0,
31 _ => return None,
32 };
33 Some(Length(pt))
34 }
35
36 pub fn max(self, other: Length) -> Length {
37 Length(self.0.max(other.0))
38 }
39
40 pub fn min(self, other: Length) -> Length {
41 Length(self.0.min(other.0))
42 }
43
44 pub(crate) fn is_positive(self) -> bool {
45 self.0 > 0.0
46 }
47}
48
49impl Add for Length {
50 type Output = Length;
51 fn add(self, rhs: Length) -> Length {
52 Length(self.0 + rhs.0)
53 }
54}
55
56impl Sub for Length {
57 type Output = Length;
58 fn sub(self, rhs: Length) -> Length {
59 Length(self.0 - rhs.0)
60 }
61}
62
63impl Neg for Length {
64 type Output = Length;
65 fn neg(self) -> Length {
66 Length(-self.0)
67 }
68}
69
70impl Mul<f64> for Length {
71 type Output = Length;
72 fn mul(self, rhs: f64) -> Length {
73 Length(self.0 * rhs)
74 }
75}
76
77impl Div<Length> for Length {
78 type Output = f64;
79 fn div(self, rhs: Length) -> f64 {
80 self.0 / rhs.0
81 }
82}
83
84impl std::fmt::Display for Length {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "{}pt", self.0)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn arithmetic() {
96 assert_eq!(Length(2.0) + Length(3.0), Length(5.0));
97 assert_eq!(-Length(1.0), Length(-1.0));
98 assert!(Length::pt(3.0) < Length::pt(4.0));
99 assert_eq!(Length(6.0) / Length(3.0), 2.0);
100 assert_eq!(Length(2.0) * 1.5, Length(3.0));
101 let mut acc = Length(1.0);
102 acc += Length(2.5);
103 assert_eq!(acc, Length(3.5));
104 }
105}