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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::prelude::*;
use num_traits::cast::AsPrimitive;
pub type F32 = ordered_float::NotNan<f32>;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, strum::Display, PartialOrd, Ord)]
pub enum Operator {
#[strum(to_string = "+")] Plus,
#[strum(to_string = "-")] Minus,
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, SmartDefault, PartialOrd, Ord)]
pub enum Unit {
#[default]
Zero,
Px(F32),
Em(F32),
Rem(F32),
Vw(F32),
Vh(F32),
Vmin(F32),
Vmax(F32),
Fr(F32),
Percent(F32),
Duration(F32),
Calc(Box<Unit>, Operator, Box<Unit>),
}
impl Unit {
#[inline] pub fn calc(left: Self, op: Operator, right: Self) -> Self { Self::Calc(Box::new(left), op, Box::new(right)) }
#[inline] pub fn px<T: AsPrimitive<f32>>(x: T) -> Self { Self::Px( F32::new(x.as_()).unwrap()) }
#[inline] pub fn em<T: AsPrimitive<f32>>(x: T) -> Self { Self::Em( F32::new(x.as_()).unwrap()) }
#[inline] pub fn rem<T: AsPrimitive<f32>>(x: T) -> Self { Self::Rem( F32::new(x.as_()).unwrap()) }
#[inline] pub fn vw<T: AsPrimitive<f32>>(x: T) -> Self { Self::Vw( F32::new(x.as_()).unwrap()) }
#[inline] pub fn vh<T: AsPrimitive<f32>>(x: T) -> Self { Self::Vh( F32::new(x.as_()).unwrap()) }
#[inline] pub fn vmin<T: AsPrimitive<f32>>(x: T) -> Self { Self::Vmin( F32::new(x.as_()).unwrap()) }
#[inline] pub fn vmax<T: AsPrimitive<f32>>(x: T) -> Self { Self::Vmax( F32::new(x.as_()).unwrap()) }
#[inline] pub fn fr<T: AsPrimitive<f32>>(x: T) -> Self { Self::Fr( F32::new(x.as_()).unwrap()) }
#[inline] pub fn pct<T: AsPrimitive<f32>>(x: T) -> Self { Self::Percent( F32::new(x.as_()).unwrap()) }
#[inline] pub fn dur<T: AsPrimitive<f32>>(x: T) -> Self { Self::Duration(F32::new(x.as_()).unwrap()) }
}
#[rustfmt::skip]
impl std::fmt::Display for Unit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Zero => "0".fmt(f),
Self::Px(x) => write!(f, "{}px", x),
Self::Em(x) => write!(f, "{}em", x),
Self::Rem(x) => write!(f, "{}rem", x),
Self::Vw(x) => write!(f, "{}vw", x),
Self::Vh(x) => write!(f, "{}vh", x),
Self::Vmin(x) => write!(f, "{}vmin", x),
Self::Vmax(x) => write!(f, "{}vmax", x),
Self::Fr(x) => write!(f, "{}fr", x),
Self::Percent(x) => write!(f, "{}%", x),
Self::Duration(x) => write!(f, "{}ms", x),
Self::Calc(left, op, right) => write!(f, "calc({} {} {})", left, op, right),
}
}
}
#[rustfmt::skip]
#[macro_export]
macro_rules! unit {
(0) => { $crate::units::Unit::Zero };
($e:literal $(px)?) => { $crate::units::Unit::px($e) };
($e:literal ms) => { $crate::units::Unit::dur($e) };
($e:literal $frag:ident) => { $crate::units::Unit::$frag($e) };
($e:literal %) => { $crate::units::Unit::pct($e) };
($e:ident $(px)?) => { $crate::units::Unit::px($e) };
($e:ident ms) => { $crate::units::Unit::dur($e) };
($e:ident $frag:ident) => { $crate::units::Unit::$frag($e) };
($e:ident %) => { $crate::units::Unit::pct($e) };
(($($e:tt)+) $(px)?) => { $crate::units::Unit::px($($e)+) };
(($($e:tt)+) ms) => { $crate::units::Unit::dur($($e)+) };
(($($e:tt)+) $frag:ident) => { $crate::units::Unit::$frag($($e)+) };
(($($e:tt)+) %) => { $crate::units::Unit::pct($($e)+) };
($e1:literal $frag1:tt + $e2:literal $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Plus, $crate::unit!($e2 $frag2)) };
($e1:ident $frag1:tt + $e2:literal $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Plus, $crate::unit!($e2 $frag2)) };
($e1:literal $frag1:tt + $e2:ident $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Plus, $crate::unit!($e2 $frag2)) };
($e1:ident $frag1:tt + $e2:ident $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Plus, $crate::unit!($e2 $frag2)) };
($e1:literal $frag1:tt - $e2:literal $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Minus, $crate::unit!($e2 $frag2)) };
($e1:ident $frag1:tt - $e2:literal $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Minus, $crate::unit!($e2 $frag2)) };
($e1:literal $frag1:tt - $e2:ident $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Minus, $crate::unit!($e2 $frag2)) };
($e1:ident $frag1:tt - $e2:ident $frag2:tt) => { $crate::units::Unit::calc($crate::unit!($e1 $frag1), $crate::units::Operator::Minus, $crate::unit!($e2 $frag2)) };
}