1use crate::style::prop_validation::TokenExpected;
2
3#[derive(Debug, Clone)]
4pub enum Length {
5 Cm(f32),
7 Mm(f32),
8 Q(f32),
9 In(f32),
10 Pc(f32),
11 Pt(f32),
12 Px(f32),
13
14 Cap(f32),
18 Ch(f32),
19 Em(f32),
20 Ex(f32),
21 Ic(f32),
22 Lh(f32),
23
24 RCap(f32),
26 RCh(f32),
27 REm(f32),
28 REx(f32),
29 RIc(f32),
30 RLh(f32),
31
32 Vh(f32),
34 Vw(f32),
35 VMax(f32),
36 VMin(f32),
37 Vb(f32),
38 Vi(f32),
39
40 Cqw(f32),
42 Cqh(f32),
43 Cqi(f32),
44 Cqb(f32),
45 CqMin(f32),
46 CqMax(f32),
47}
48
49#[derive(Debug, Clone)]
50pub enum Angle {
51 Deg(f32),
52 Grad(f32),
53 Rad(f32),
54 Turn(f32),
55}
56
57#[derive(Debug, Clone)]
58pub enum Time {
59 Sec(f32),
60 Milli(f32),
61}
62
63#[derive(Debug, Clone)]
64pub enum Frequency {}
65
66#[derive(Debug, Clone)]
67pub enum Resolution {
68 Dpi(f32),
69 Dpcm(f32),
70 Dppx(f32),
71}
72
73#[derive(Debug, Clone, derive_more::From)]
74pub enum Dimension {
75 #[from]
76 Length(Length),
77 #[from]
78 Angle(Angle),
79 #[from]
80 Time(Time),
81 #[from]
82 Frequency(Frequency),
83 #[from]
84 Resolution(Resolution),
85}
86
87#[derive(Debug, Clone, derive_more::From)]
88pub struct Percentage(f32);
89
90#[derive(Debug, Clone, derive_more::From)]
91pub struct Hash(String);
92
93#[derive(Debug, Clone, derive_more::From)]
94pub enum Unit {
95 #[from]
96 Integer(i32),
97 #[from]
98 Number(f32),
99 #[from]
100 Dimension(Dimension),
101 #[from]
102 Percentage(Percentage),
103 #[from]
104 String(String),
105 #[from]
106 Hash(Hash),
107
108 #[from]
109 Function {
110 name: String,
111 required_return_type: TokenExpected,
112 params: Vec<Unit>,
113 },
114
115 #[from]
116 Shorthand(Box<Unit>, Box<Unit>),
117
118 UnknownIdent(String),
119}
120
121impl Length {
122 pub fn get(&self) -> f32 {
123 match self {
124 Length::Cm(num) => *num,
125 Length::Mm(num) => *num,
126 Length::Q(num) => *num,
127 Length::In(num) => *num,
128 Length::Pc(num) => *num,
129 Length::Pt(num) => *num,
130 Length::Px(num) => *num,
131
132 Length::Cap(num) => *num,
133 Length::Ch(num) => *num,
134 Length::Em(num) => *num,
135 Length::Ex(num) => *num,
136 Length::Ic(num) => *num,
137 Length::Lh(num) => *num,
138
139 Length::RCap(num) => *num,
140 Length::RCh(num) => *num,
141 Length::REm(num) => *num,
142 Length::REx(num) => *num,
143 Length::RIc(num) => *num,
144 Length::RLh(num) => *num,
145
146 Length::Vh(num) => *num,
147 Length::Vw(num) => *num,
148 Length::VMax(num) => *num,
149 Length::VMin(num) => *num,
150 Length::Vb(num) => *num,
151 Length::Vi(num) => *num,
152
153 Length::Cqw(num) => *num,
154 Length::Cqh(num) => *num,
155 Length::Cqi(num) => *num,
156 Length::Cqb(num) => *num,
157 Length::CqMin(num) => *num,
158 Length::CqMax(num) => *num,
159 }
160 }
161
162 pub fn from_pair(num: f32, unit: &str) -> Option<Self> {
163 match unit {
164 "cm" => Some(Self::Cm(num)),
165 "mm" => Some(Self::Mm(num)),
166 "Q" => Some(Self::Q(num)),
167 "in" => Some(Self::In(num)),
168 "pc" => Some(Self::Pc(num)),
169 "pt" => Some(Self::Pt(num)),
170 "px" => Some(Self::Px(num)),
171
172 "cap" => Some(Self::Cap(num)),
173 "ch" => Some(Self::Ch(num)),
174 "em" => Some(Self::Em(num)),
175 "ex" => Some(Self::Ex(num)),
176 "ic" => Some(Self::Ic(num)),
177 "lh" => Some(Self::Lh(num)),
178
179 "rcap" => Some(Self::RCap(num)),
180 "rch" => Some(Self::RCh(num)),
181 "rem" => Some(Self::REm(num)),
182 "rex" => Some(Self::REx(num)),
183 "ric" => Some(Self::RIc(num)),
184 "rlh" => Some(Self::RLh(num)),
185
186 "vh" => Some(Self::Vh(num)),
187 "vw" => Some(Self::Vw(num)),
188 "vMax" => Some(Self::VMax(num)),
189 "vMin" => Some(Self::VMin(num)),
190 "vb" => Some(Self::Vb(num)),
191 "vi" => Some(Self::Vi(num)),
192
193 "cqw" => Some(Self::Cqw(num)),
194 "cqh" => Some(Self::Cqh(num)),
195 "cqi" => Some(Self::Cqi(num)),
196 "cqb" => Some(Self::Cqb(num)),
197 "cqmin" => Some(Self::CqMin(num)),
198 "cqmax" => Some(Self::CqMax(num)),
199
200 _ => None,
201 }
202 }
203
204 pub fn computed_value(self) -> f32 {
206 match self {
207 Length::Cm(cm) => cm * (96f32 / 2.54f32),
208 Length::Mm(mm) => mm * (96f32 / 25.4f32),
209 Length::Q(q) => q * (96f32 / 101.6f32),
210 Length::In(inches) => inches * (96f32 / 1f32),
211 Length::Pc(pc) => pc * (96f32 / 6f32),
212 Length::Pt(pt) => pt * (96f32 / 72f32),
213 Length::Px(px) => px,
214
215 _ => unimplemented!(),
216 }
217 }
218}
219
220impl Angle {
221 pub fn get(&self) -> f32 {
222 match self {
223 Angle::Deg(num) => *num,
224 Angle::Grad(num) => *num,
225 Angle::Rad(num) => *num,
226 Angle::Turn(num) => *num,
227 }
228 }
229
230 pub fn from_pair(num: f32, unit: &str) -> Option<Self> {
231 match unit {
232 "deg" => Some(Self::Deg(num)),
233 "grad" => Some(Self::Grad(num)),
234 "rad" => Some(Self::Rad(num)),
235 "turn" => Some(Self::Turn(num)),
236
237 _ => None,
238 }
239 }
240
241 pub fn computed_value(self) -> f32 {
243 match self {
244 Angle::Deg(deg) => deg.to_radians(),
245 Angle::Grad(grad) => grad * std::f32::consts::PI / 200f32,
246 Angle::Rad(rad) => rad,
247 Angle::Turn(turn) => turn * std::f32::consts::TAU,
248 }
249 }
250}
251
252impl Time {
253 pub fn get(&self) -> f32 {
254 match self {
255 Time::Sec(num) => *num,
256 Time::Milli(num) => *num,
257 }
258 }
259
260 pub fn computed_value(self) -> f32 {
261 unimplemented!()
262 }
263}
264
265impl Frequency {
266 pub fn computed_value(self) -> f32 {
267 unimplemented!()
268 }
269}
270
271impl Resolution {
272 pub fn get(&self) -> f32 {
273 match self {
274 Resolution::Dpi(num) => *num,
275 Resolution::Dpcm(num) => *num,
276 Resolution::Dppx(num) => *num,
277 }
278 }
279
280 pub fn from_pair(num: f32, unit: &str) -> Option<Self> {
282 match unit {
283 "dpi" => Some(Self::Dpi(num)),
284 "dpcm" => Some(Self::Dpcm(num)),
285 "dppx" => Some(Self::Dppx(num)),
286 "x" => Some(Self::Dppx(num)),
287
288 _ => None,
289 }
290 }
291
292 pub fn computed_value(self) -> f32 {
294 match self {
295 Resolution::Dpi(dpi) => dpi / 96f32,
296 Resolution::Dpcm(dpcm) => dpcm * 2.54f32 / 96f32,
297 Resolution::Dppx(x) => x,
298 }
299 }
300}
301
302impl Dimension {
303 pub fn from_pair(num: f32, unit: &str) -> Option<Self> {
304 if let Some(length) = Length::from_pair(num, unit) {
305 Some(Self::Length(length))
306 } else if let Some(angle) = Angle::from_pair(num, unit) {
307 Some(Self::Angle(angle))
308 } else if let Some(resolution) = Resolution::from_pair(num, unit) {
309 Some(Self::Resolution(resolution))
310 } else {
311 None
312 }
313 }
314}
315
316impl Into<f32> for Length {
317 fn into(self) -> f32 {
318 self.get()
319 }
320}
321
322impl Into<f32> for Angle {
323 fn into(self) -> f32 {
324 match self {
325 Angle::Deg(num) => num,
326 Angle::Grad(num) => num,
327 Angle::Rad(num) => num,
328 Angle::Turn(num) => num,
329 }
330 }
331}
332
333impl Into<f32> for Time {
334 fn into(self) -> f32 {
335 match self {
336 Self::Sec(num) => num,
337 Self::Milli(num) => num,
338 }
339 }
340}
341
342impl Into<f32> for Resolution {
343 fn into(self) -> f32 {
344 match self {
345 Resolution::Dpi(val) => val,
346 Resolution::Dpcm(val) => val,
347 Resolution::Dppx(val) => val,
348 }
349 }
350}
351
352impl Into<f32> for Dimension {
353 fn into(self) -> f32 {
354 match self {
355 Dimension::Length(length) => length.into(),
356 Dimension::Angle(angle) => angle.into(),
357 Dimension::Time(_) => unimplemented!(),
358 Dimension::Frequency(_) => unimplemented!(),
359 Dimension::Resolution(resolution) => resolution.into(),
360 }
361 }
362}
363
364impl Into<f32> for Percentage {
365 fn into(self) -> f32 {
366 self.0
367 }
368}
369
370impl std::fmt::Display for Length {
371 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
372 match self {
373 Length::Cm(val) => write!(f, "{val}cm"),
374 Length::Mm(val) => write!(f, "{val}mm"),
375 Length::Q(val) => write!(f, "{val}Q"),
376 Length::In(val) => write!(f, "{val}in"),
377 Length::Pc(val) => write!(f, "{val}pc"),
378 Length::Pt(val) => write!(f, "{val}pt"),
379 Length::Px(val) => write!(f, "{val}px"),
380
381 Length::Cap(val) => write!(f, "{val}cap"),
382 Length::Ch(val) => write!(f, "{val}ch"),
383 Length::Em(val) => write!(f, "{val}em"),
384 Length::Ex(val) => write!(f, "{val}ex"),
385 Length::Ic(val) => write!(f, "{val}ic"),
386 Length::Lh(val) => write!(f, "{val}lh"),
387
388 Length::RCap(val) => write!(f, "{val}rcap"),
389 Length::RCh(val) => write!(f, "{val}rch"),
390 Length::REm(val) => write!(f, "{val}rem"),
391 Length::REx(val) => write!(f, "{val}rex"),
392 Length::RIc(val) => write!(f, "{val}ric"),
393 Length::RLh(val) => write!(f, "{val}rlh"),
394
395 Length::Vh(val) => write!(f, "{val}vh"),
396 Length::Vw(val) => write!(f, "{val}vw"),
397 Length::VMax(val) => write!(f, "{val}vmax"),
398 Length::VMin(val) => write!(f, "{val}vmin"),
399 Length::Vb(val) => write!(f, "{val}vb"),
400 Length::Vi(val) => write!(f, "{val}vi"),
401
402 Length::Cqw(val) => write!(f, "{val}cqw"),
403 Length::Cqh(val) => write!(f, "{val}cqh"),
404 Length::Cqi(val) => write!(f, "{val}cqi"),
405 Length::Cqb(val) => write!(f, "{val}cqb"),
406 Length::CqMin(val) => write!(f, "{val}cqmin"),
407 Length::CqMax(val) => write!(f, "{val}cqmax"),
408 }
409 }
410}
411
412impl std::fmt::Display for Angle {
413 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414 match self {
415 Angle::Deg(val) => write!(f, "{val}deg"),
416 Angle::Grad(val) => write!(f, "{val}grad"),
417 Angle::Rad(val) => write!(f, "{val}rad"),
418 Angle::Turn(val) => write!(f, "{val}turn"),
419 }
420 }
421}
422
423impl std::fmt::Display for Resolution {
424 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
425 match self {
426 Resolution::Dpi(val) => write!(f, "{val}dpi"),
427 Resolution::Dpcm(val) => write!(f, "{val}dpcm"),
428 Resolution::Dppx(val) => write!(f, "{val}x"),
429 }
430 }
431}
432
433impl std::fmt::Display for Dimension {
434 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435 match self {
436 Dimension::Length(length) => write!(f, "{length}"),
437 Dimension::Angle(angle) => write!(f, "{angle}"),
438 Dimension::Time(time) => todo!(),
439 Dimension::Frequency(frequency) => todo!(),
440 Dimension::Resolution(resolution) => write!(f, "{resolution}"),
441 }
442 }
443}
444
445impl std::fmt::Display for Unit {
446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447 match self {
448 Unit::Integer(int) => write!(f, "{int}"),
449 Unit::Number(num) => write!(f, "{num}"),
450 Unit::Dimension(dimension) => write!(f, "{dimension}"),
451 Unit::Percentage(percentage) => write!(f, "{}", percentage.0),
452 Unit::String(string) => write!(f, r#""{string}""#),
453 Unit::Hash(hash) => write!(f, "#{}", hash.0),
454 Unit::Shorthand(val1, val2) => write!(f, "{val1}/{val2}"),
455 Unit::UnknownIdent(ident) => write!(f, "{ident}"),
456 Unit::Function {
457 name,
458 required_return_type,
459 params,
460 } => {
461 let param_string: String = params
462 .iter()
463 .map(|x| x.to_string())
464 .collect::<Vec<_>>()
465 .join(", ");
466
467 write!(f, "{name}({param_string})")
468 }
469 }
470 }
471}