1use crate::data_type::{Angle, Length, Percentage, Time};
15
16pub trait IntoF32: Copy {
23 fn into_f32(self) -> f32;
25}
26
27impl IntoF32 for f32 {
28 fn into_f32(self) -> f32 {
29 self
30 }
31}
32
33impl IntoF32 for i32 {
34 fn into_f32(self) -> f32 {
35 self as f32
36 }
37}
38
39impl IntoF32 for u32 {
40 fn into_f32(self) -> f32 {
41 self as f32
42 }
43}
44
45pub fn px(v: impl IntoF32) -> Length {
49 Length::Px(v.into_f32())
50}
51
52pub fn rpx(v: impl IntoF32) -> Length {
54 Length::Rpx(v.into_f32())
55}
56
57pub fn ppx(v: impl IntoF32) -> Length {
59 Length::Ppx(v.into_f32())
60}
61
62pub fn em(v: impl IntoF32) -> Length {
64 Length::Em(v.into_f32())
65}
66
67pub fn rem(v: impl IntoF32) -> Length {
69 Length::Rem(v.into_f32())
70}
71
72pub fn vh(v: impl IntoF32) -> Length {
74 Length::Vh(v.into_f32())
75}
76
77pub fn vw(v: impl IntoF32) -> Length {
79 Length::Vw(v.into_f32())
80}
81
82pub const ZERO: Length = Length::Zero;
84
85pub trait LengthExt: Copy {
90 fn px(self) -> Length;
92 fn rpx(self) -> Length;
94 fn ppx(self) -> Length;
96 fn em(self) -> Length;
98 fn rem(self) -> Length;
100 fn vh(self) -> Length;
102 fn vw(self) -> Length;
104}
105
106impl<T: IntoF32> LengthExt for T {
107 fn px(self) -> Length {
108 Length::Px(self.into_f32())
109 }
110 fn rpx(self) -> Length {
111 Length::Rpx(self.into_f32())
112 }
113 fn ppx(self) -> Length {
114 Length::Ppx(self.into_f32())
115 }
116 fn em(self) -> Length {
117 Length::Em(self.into_f32())
118 }
119 fn rem(self) -> Length {
120 Length::Rem(self.into_f32())
121 }
122 fn vh(self) -> Length {
123 Length::Vh(self.into_f32())
124 }
125 fn vw(self) -> Length {
126 Length::Vw(self.into_f32())
127 }
128}
129
130pub fn percent(v: impl IntoF32) -> Percentage {
134 Percentage(v.into_f32())
135}
136
137pub trait PercentExt: Copy {
139 fn percent(self) -> Percentage;
141}
142
143impl<T: IntoF32> PercentExt for T {
144 fn percent(self) -> Percentage {
145 Percentage(self.into_f32())
146 }
147}
148
149pub fn deg(v: impl IntoF32) -> Angle {
153 Angle::Deg(v.into_f32())
154}
155
156pub fn rad(v: impl IntoF32) -> Angle {
158 Angle::Rad(v.into_f32())
159}
160
161pub fn turn(v: impl IntoF32) -> Angle {
163 Angle::Turn(v.into_f32())
164}
165
166pub trait AngleExt: Copy {
168 fn deg(self) -> Angle;
170 fn rad(self) -> Angle;
172 fn turn(self) -> Angle;
174}
175
176impl<T: IntoF32> AngleExt for T {
177 fn deg(self) -> Angle {
178 Angle::Deg(self.into_f32())
179 }
180 fn rad(self) -> Angle {
181 Angle::Rad(self.into_f32())
182 }
183 fn turn(self) -> Angle {
184 Angle::Turn(self.into_f32())
185 }
186}
187
188pub fn s(v: impl IntoF32) -> Time {
192 Time::S(v.into_f32())
193}
194
195pub fn ms(v: impl IntoF32) -> Time {
197 Time::Ms(v.into_f32())
198}
199
200pub trait TimeExt: Copy {
202 fn s(self) -> Time;
204 fn ms(self) -> Time;
206}
207
208impl<T: IntoF32> TimeExt for T {
209 fn s(self) -> Time {
210 Time::S(self.into_f32())
211 }
212 fn ms(self) -> Time {
213 Time::Ms(self.into_f32())
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220 use crate::to_css::ToCss;
221
222 #[test]
223 fn length_free_fns() {
224 assert_eq!(px(8).to_css_string(), "8px");
225 assert_eq!(rpx(750).to_css_string(), "750rpx");
226 assert_eq!(ppx(2).to_css_string(), "2ppx");
227 assert_eq!(em(1.5).to_css_string(), "1.5em");
228 assert_eq!(rem(2).to_css_string(), "2rem");
229 assert_eq!(vh(50).to_css_string(), "50vh");
230 assert_eq!(vw(100).to_css_string(), "100vw");
231 }
232
233 #[test]
234 fn length_methods_on_i32() {
235 assert_eq!(8.px().to_css_string(), "8px");
236 assert_eq!(750.rpx().to_css_string(), "750rpx");
237 assert_eq!(2.ppx().to_css_string(), "2ppx");
238 assert_eq!(1.em().to_css_string(), "1em");
239 assert_eq!(2.rem().to_css_string(), "2rem");
240 assert_eq!(50.vh().to_css_string(), "50vh");
241 assert_eq!(100.vw().to_css_string(), "100vw");
242 }
243
244 #[test]
245 fn length_methods_on_f32() {
246 assert_eq!(0.5_f32.px().to_css_string(), "0.5px");
247 assert_eq!(1.5_f32.em().to_css_string(), "1.5em");
248 assert_eq!(0.5_f32.rem().to_css_string(), "0.5rem");
249 assert_eq!(0.5_f32.vh().to_css_string(), "0.5vh");
250 assert_eq!(0.5_f32.vw().to_css_string(), "0.5vw");
251 assert_eq!(0.5_f32.rpx().to_css_string(), "0.5rpx");
252 assert_eq!(0.5_f32.ppx().to_css_string(), "0.5ppx");
253 }
254
255 #[test]
256 fn percent_helpers() {
257 assert_eq!(percent(50).to_css_string(), "50%");
258 assert_eq!(50.percent().to_css_string(), "50%");
259 assert_eq!(33.3_f32.percent().to_css_string(), "33.3%");
260 }
261
262 #[test]
263 fn angle_helpers() {
264 assert_eq!(deg(90).to_css_string(), "90deg");
265 assert_eq!(rad(1).to_css_string(), "1rad");
266 assert_eq!(turn(1).to_css_string(), "1turn");
267 assert_eq!(45.deg().to_css_string(), "45deg");
268 assert_eq!(2.rad().to_css_string(), "2rad");
269 assert_eq!(0.5_f32.turn().to_css_string(), "0.5turn");
270 assert_eq!(0.5_f32.deg().to_css_string(), "0.5deg");
271 assert_eq!(0.5_f32.rad().to_css_string(), "0.5rad");
272 }
273
274 #[test]
275 fn time_helpers() {
276 assert_eq!(s(1).to_css_string(), "1s");
277 assert_eq!(ms(300).to_css_string(), "300ms");
278 assert_eq!(1.s().to_css_string(), "1s");
279 assert_eq!(300.ms().to_css_string(), "300ms");
280 assert_eq!(0.5_f32.s().to_css_string(), "0.5s");
281 assert_eq!(1.5_f32.ms().to_css_string(), "1.5ms");
282 }
283
284 #[test]
285 fn into_f32_for_u32() {
286 assert_eq!(IntoF32::into_f32(7_u32), 7.0);
287 assert_eq!(7_u32.px().to_css_string(), "7px");
288 }
289
290 #[test]
291 fn zero_constant() {
292 assert_eq!(ZERO.to_css_string(), "0");
293 }
294}