lewp_css/domain/numbers/
css_number.rs1use {
5 super::CssNumberConversionError::*,
6 crate::{
7 domain::{
8 numbers::{CssNumberConversionError, CssNumberNewType},
9 units::{AppUnitsPer, Unit},
10 },
11 CustomParseError,
12 },
13 cssparser::{ParseError, ToCss},
14 std::{
15 fmt::{Debug, Display},
16 hash::Hash,
17 ops::*,
18 },
19};
20
21pub trait CssNumber:
22 Sized
23 + Copy
24 + Clone
25 + PartialEq<Self>
26 + Eq
27 + PartialOrd
28 + Ord
29 + Hash
30 + ToCss
31 + Default
32 + Add<Self, Output = Self>
33 + AddAssign<Self>
34 + Sub<Self, Output = Self>
35 + SubAssign<Self>
36 + Mul<Self, Output = Self>
37 + MulAssign<Self>
38 + Div<Self, Output = Self>
39 + DivAssign<Self>
40 + Rem<Self, Output = Self>
41 + RemAssign<Self>
42 + Neg<Output = Self>
43 + Debug
44 + Display
45 + Deref
46 + From<u16>
47 + From<u8>
48 + CssNumberNewType<Self>
49 + Unit<Number = Self>
50 + AppUnitsPer
51{
52 const Zero: Self;
53
54 const One: Self;
55
56 const Maximum: Self;
57
58 const Minimum: Self;
59
60 const DotsPerInch: Self;
61
62 const CentimetresPerInch: Self;
63
64 #[inline(always)]
65 fn new(value: f32) -> Result<Self, CssNumberConversionError> {
66 const NegativeZero: f32 = -0.0_f32;
67 const PositiveZero: f32 = 0.0_f32;
68
69 if value.is_finite() {
70 if value == NegativeZero {
71 if Self::can_be_negative() {
72 Ok(Self::_construct(PositiveZero))
73 } else {
74 Err(NegativeNumberMayNotBeAllowed)
75 }
76 } else {
77 Ok(Self::_construct(value))
78 }
79 } else if !Self::can_be_negative() && value.is_sign_negative() {
80 Err(NegativeNumberMayNotBeAllowed)
81 } else if value.is_infinite() {
82 Err(InfinityIsNotAllowed)
83 } else if value.is_nan() {
84 Err(NotANumberIsNotAllowed)
85 } else {
86 unreachable!("What other kind of f32 is there?");
87 }
88 }
89
90 fn as_f32(&self) -> f32;
91
92 fn as_u32(&self) -> u32;
93
94 #[inline(always)]
95 fn round(self) -> Self {
96 Self::_construct(self.to_f32().round())
97 }
98
99 #[inline(always)]
100 fn abs(self) -> Self {
101 Self::_construct(self.to_f32().abs())
102 }
103
104 #[inline(always)]
105 fn clamp(value: f32) -> Self {
106 if value.is_infinite() {
107 if value.is_sign_positive() {
108 Self::Maximum
109 } else {
110 Self::Minimum
111 }
112 } else if value.is_sign_negative() && !Self::can_be_negative() {
113 Self::Zero
114 } else {
115 Self::_construct(value)
116 }
117 }
118
119 #[inline(always)]
120 fn can_be_negative() -> bool {
121 Self::Minimum.is_negative()
122 }
123
124 #[doc(hidden)]
125 fn _construct(value: f32) -> Self;
126
127 fn parseNumber<'i>(
128 value: f32,
129 _int_value: Option<i32>,
130 ) -> Result<Self, ParseError<'i, CustomParseError<'i>>>;
131}