swc_css_ast/
value.rs

1use std::hash::{Hash, Hasher};
2
3use is_macro::Is;
4use string_enum::StringEnum;
5use swc_atoms::Atom;
6use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
7
8use crate::Function;
9
10#[ast_node("Ident")]
11#[derive(Eq, PartialOrd, Ord, Hash)]
12pub struct Ident {
13    pub span: Span,
14
15    pub value: Atom,
16    pub raw: Option<Atom>,
17}
18
19impl EqIgnoreSpan for Ident {
20    #[inline]
21    fn eq_ignore_span(&self, other: &Self) -> bool {
22        self.value == other.value
23    }
24}
25
26impl PartialEq<str> for Ident {
27    #[inline]
28    fn eq(&self, other: &str) -> bool {
29        &*self.value == other
30    }
31}
32
33impl Take for Ident {
34    #[inline]
35    fn dummy() -> Self {
36        Self {
37            span: Default::default(),
38            value: Default::default(),
39            raw: Default::default(),
40        }
41    }
42}
43
44#[ast_node("CustomIdent")]
45#[derive(Eq, Hash)]
46pub struct CustomIdent {
47    pub span: Span,
48
49    pub value: Atom,
50    pub raw: Option<Atom>,
51}
52
53impl EqIgnoreSpan for CustomIdent {
54    #[inline]
55    fn eq_ignore_span(&self, other: &Self) -> bool {
56        self.value == other.value
57    }
58}
59
60#[ast_node("DashedIdent")]
61#[derive(Eq, Hash)]
62pub struct DashedIdent {
63    pub span: Span,
64
65    pub value: Atom,
66    pub raw: Option<Atom>,
67}
68
69impl EqIgnoreSpan for DashedIdent {
70    #[inline]
71    fn eq_ignore_span(&self, other: &Self) -> bool {
72        self.value == other.value
73    }
74}
75
76impl PartialEq<str> for DashedIdent {
77    #[inline]
78    fn eq(&self, other: &str) -> bool {
79        &*self.value == other
80    }
81}
82
83#[ast_node("CustomPropertyName")]
84#[derive(Eq, Hash)]
85pub struct CustomPropertyName {
86    pub span: Span,
87
88    pub value: Atom,
89    pub raw: Option<Atom>,
90}
91
92impl EqIgnoreSpan for CustomPropertyName {
93    fn eq_ignore_span(&self, other: &Self) -> bool {
94        self.value == other.value
95    }
96}
97
98/// Quoted string.
99#[ast_node("String")]
100#[derive(Eq, Hash)]
101pub struct Str {
102    pub span: Span,
103
104    pub value: Atom,
105    pub raw: Option<Atom>,
106}
107
108impl EqIgnoreSpan for Str {
109    fn eq_ignore_span(&self, other: &Self) -> bool {
110        self.value == other.value
111    }
112}
113
114#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)]
115#[cfg_attr(
116    feature = "rkyv",
117    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
118)]
119#[cfg_attr(
120    feature = "rkyv",
121    rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
122        __S::Error: rkyv::rancor::Source))
123)]
124#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
125#[cfg_attr(feature = "rkyv", repr(u32))]
126pub enum DelimiterValue {
127    /// `,`
128    Comma,
129    /// `/`
130    Solidus,
131    /// `;`
132    Semicolon,
133}
134
135#[ast_node("Delimiter")]
136#[derive(Eq, Hash, EqIgnoreSpan)]
137pub struct Delimiter {
138    pub span: Span,
139    pub value: DelimiterValue,
140}
141
142// TODO small AST improve for `CurrentColorOrSystemColor` and
143// `NamedColorOrTransparent`
144#[ast_node]
145#[derive(Eq, Hash, Is, EqIgnoreSpan)]
146pub enum Color {
147    #[tag("AbsoluteColorBase")]
148    AbsoluteColorBase(AbsoluteColorBase),
149    #[tag("Ident")]
150    CurrentColorOrSystemColor(Ident),
151    // <device-cmyk()> only
152    #[tag("Function")]
153    Function(Function),
154}
155
156#[ast_node]
157#[derive(Eq, Hash, Is, EqIgnoreSpan)]
158pub enum AbsoluteColorBase {
159    #[tag("HexColor")]
160    HexColor(HexColor),
161    #[tag("Ident")]
162    NamedColorOrTransparent(Ident),
163    #[tag("Function")]
164    Function(Function),
165}
166
167#[ast_node("HexColor")]
168#[derive(Eq, Hash, EqIgnoreSpan)]
169pub struct HexColor {
170    /// Includes `#`
171    pub span: Span,
172    /// Does **not** include `#`
173    pub value: Atom,
174    /// Does **not** include `#`
175    pub raw: Option<Atom>,
176}
177
178#[ast_node]
179#[derive(Eq, Hash, Is, EqIgnoreSpan)]
180pub enum AlphaValue {
181    #[tag("Number")]
182    Number(Number),
183    #[tag("Percentage")]
184    Percentage(Percentage),
185}
186
187#[ast_node]
188#[derive(Eq, Hash, Is, EqIgnoreSpan)]
189pub enum Hue {
190    #[tag("Number")]
191    Number(Number),
192    #[tag("Angle")]
193    Angle(Angle),
194}
195
196#[ast_node]
197#[derive(Eq, Hash, Is, EqIgnoreSpan)]
198pub enum CmykComponent {
199    #[tag("Number")]
200    Number(Number),
201    #[tag("Percentage")]
202    Percentage(Percentage),
203    #[tag("Function")]
204    Function(Function),
205}
206
207#[ast_node]
208#[derive(Eq, Hash, Is, EqIgnoreSpan)]
209pub enum Dimension {
210    #[tag("Length")]
211    Length(Length),
212
213    #[tag("Angle")]
214    Angle(Angle),
215
216    #[tag("Time")]
217    Time(Time),
218
219    #[tag("Frequency")]
220    Frequency(Frequency),
221
222    #[tag("Resolution")]
223    Resolution(Resolution),
224
225    #[tag("Flex")]
226    Flex(Flex),
227
228    #[tag("UnknownDimension")]
229    UnknownDimension(UnknownDimension),
230}
231
232#[ast_node("Length")]
233#[derive(Eq, Hash, EqIgnoreSpan)]
234pub struct Length {
235    pub span: Span,
236    pub value: Number,
237    pub unit: Ident,
238}
239
240#[ast_node("Angle")]
241#[derive(Eq, Hash, EqIgnoreSpan)]
242pub struct Angle {
243    pub span: Span,
244    pub value: Number,
245    pub unit: Ident,
246}
247
248#[ast_node("Time")]
249#[derive(Eq, Hash, EqIgnoreSpan)]
250pub struct Time {
251    pub span: Span,
252    pub value: Number,
253    pub unit: Ident,
254}
255
256#[ast_node("Frequency")]
257#[derive(Eq, Hash, EqIgnoreSpan)]
258pub struct Frequency {
259    pub span: Span,
260    pub value: Number,
261    pub unit: Ident,
262}
263
264#[ast_node("Resolution")]
265#[derive(Eq, Hash, EqIgnoreSpan)]
266pub struct Resolution {
267    pub span: Span,
268    pub value: Number,
269    pub unit: Ident,
270}
271
272#[ast_node("Flex")]
273#[derive(Eq, Hash, EqIgnoreSpan)]
274pub struct Flex {
275    pub span: Span,
276    pub value: Number,
277    pub unit: Ident,
278}
279
280#[ast_node("UnknownDimension")]
281#[derive(Eq, Hash, EqIgnoreSpan)]
282pub struct UnknownDimension {
283    pub span: Span,
284    pub value: Number,
285    pub unit: Ident,
286}
287
288#[ast_node("Percentage")]
289#[derive(Eq, Hash, EqIgnoreSpan)]
290pub struct Percentage {
291    pub span: Span,
292    pub value: Number,
293}
294
295#[ast_node]
296#[derive(Eq, Hash, Is, EqIgnoreSpan)]
297pub enum LengthPercentage {
298    #[tag("Length")]
299    Length(Length),
300    #[tag("Percentage")]
301    Percentage(Percentage),
302}
303
304#[ast_node]
305#[derive(Eq, Hash, Is, EqIgnoreSpan)]
306pub enum FrequencyPercentage {
307    #[tag("Frequency")]
308    Frequency(Frequency),
309    #[tag("Percentage")]
310    Percentage(Percentage),
311}
312
313#[ast_node]
314#[derive(Eq, Hash, Is, EqIgnoreSpan)]
315pub enum AnglePercentage {
316    #[tag("Angle")]
317    Angle(Angle),
318    #[tag("Percentage")]
319    Percentage(Percentage),
320}
321
322#[ast_node]
323#[derive(Eq, Hash, Is, EqIgnoreSpan)]
324pub enum TimePercentage {
325    #[tag("Time")]
326    Time(Time),
327    #[tag("Percentage")]
328    Percentage(Percentage),
329}
330
331#[ast_node("Integer")]
332#[derive(Eq, Hash)]
333pub struct Integer {
334    pub span: Span,
335    pub value: i64,
336    pub raw: Option<Atom>,
337}
338
339impl EqIgnoreSpan for Integer {
340    fn eq_ignore_span(&self, other: &Self) -> bool {
341        self.value == other.value
342    }
343}
344
345#[ast_node("Number")]
346pub struct Number {
347    pub span: Span,
348    pub value: f64,
349    pub raw: Option<Atom>,
350}
351
352impl Eq for Number {}
353
354#[allow(clippy::derived_hash_with_manual_eq)]
355#[allow(clippy::transmute_float_to_int)]
356impl Hash for Number {
357    fn hash<H: Hasher>(&self, state: &mut H) {
358        fn integer_decode(val: f64) -> (u64, i16, i8) {
359            let bits: u64 = f64::to_bits(val);
360            let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
361            let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
362            let mantissa = if exponent == 0 {
363                (bits & 0xfffffffffffff) << 1
364            } else {
365                (bits & 0xfffffffffffff) | 0x10000000000000
366            };
367
368            exponent -= 1023 + 52;
369            (mantissa, exponent, sign)
370        }
371
372        self.span.hash(state);
373        integer_decode(self.value).hash(state);
374    }
375}
376
377impl EqIgnoreSpan for Number {
378    fn eq_ignore_span(&self, other: &Self) -> bool {
379        self.value == other.value
380    }
381}
382
383#[ast_node("Ratio")]
384#[derive(Eq, Hash, EqIgnoreSpan)]
385pub struct Ratio {
386    pub span: Span,
387    pub left: Number,
388    pub right: Option<Number>,
389}
390
391#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)]
392#[cfg_attr(
393    feature = "rkyv",
394    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
395)]
396#[cfg_attr(
397    feature = "rkyv",
398    rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
399        __S::Error: rkyv::rancor::Source))
400)]
401#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
402#[cfg_attr(feature = "rkyv", repr(u32))]
403pub enum BinOp {
404    /// `+`
405    Add,
406    /// `-`
407    Sub,
408    /// `*`
409    Mul,
410    /// `/`
411    Div,
412}
413
414#[ast_node("Url")]
415#[derive(Eq, Hash, EqIgnoreSpan)]
416pub struct Url {
417    pub span: Span,
418    pub name: Ident,
419    pub value: Option<Box<UrlValue>>,
420    pub modifiers: Option<Vec<UrlModifier>>,
421}
422
423#[ast_node]
424#[derive(Eq, Hash, Is, EqIgnoreSpan)]
425pub enum UrlValue {
426    #[tag("Str")]
427    Str(Str),
428    #[tag("UrlValueRaw")]
429    Raw(UrlValueRaw),
430}
431
432#[ast_node("UrlValueRaw")]
433#[derive(Eq, Hash, EqIgnoreSpan)]
434pub struct UrlValueRaw {
435    pub span: Span,
436
437    pub value: Atom,
438    pub raw: Option<Atom>,
439}
440
441#[ast_node]
442#[derive(Eq, Hash, Is, EqIgnoreSpan)]
443pub enum UrlModifier {
444    #[tag("Ident")]
445    Ident(Ident),
446    #[tag("Function")]
447    Function(Function),
448}
449
450#[ast_node("UnicodeRange")]
451#[derive(Eq, Hash)]
452pub struct UnicodeRange {
453    pub span: Span,
454
455    pub start: Atom,
456
457    pub end: Option<Atom>,
458    pub raw: Option<Atom>,
459}
460
461impl EqIgnoreSpan for UnicodeRange {
462    #[inline]
463    fn eq_ignore_span(&self, other: &Self) -> bool {
464        self.start == other.start && self.end == other.end
465    }
466}
467
468#[ast_node("CalcSum")]
469#[derive(Eq, Hash, EqIgnoreSpan)]
470pub struct CalcSum {
471    pub span: Span,
472    pub expressions: Vec<CalcProductOrOperator>,
473}
474
475#[ast_node]
476#[derive(Eq, Hash, Is, EqIgnoreSpan)]
477pub enum CalcProductOrOperator {
478    #[tag("CalcProduct")]
479    Product(CalcProduct),
480    #[tag("CalcOperator")]
481    Operator(CalcOperator),
482}
483
484#[ast_node("CalcProduct")]
485#[derive(Eq, Hash, EqIgnoreSpan)]
486pub struct CalcProduct {
487    pub span: Span,
488    pub expressions: Vec<CalcValueOrOperator>,
489}
490
491#[ast_node("CalcOperator")]
492#[derive(Eq, Hash, EqIgnoreSpan)]
493pub struct CalcOperator {
494    pub span: Span,
495    pub value: CalcOperatorType,
496}
497
498#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)]
499#[cfg_attr(
500    feature = "rkyv",
501    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
502)]
503#[cfg_attr(
504    feature = "rkyv",
505    rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
506        __S::Error: rkyv::rancor::Source))
507)]
508#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))]
509#[cfg_attr(feature = "rkyv-impl", repr(u32))]
510pub enum CalcOperatorType {
511    /// `+`
512    Add,
513    /// `-`
514    Sub,
515    /// `*`
516    Mul,
517    /// `/`
518    Div,
519}
520
521#[ast_node]
522#[derive(Eq, Hash, Is, EqIgnoreSpan)]
523pub enum CalcValueOrOperator {
524    #[tag("CalcValue")]
525    Value(CalcValue),
526    #[tag("CalcOperator")]
527    Operator(CalcOperator),
528}
529
530#[ast_node]
531#[derive(Eq, Hash, Is, EqIgnoreSpan)]
532pub enum CalcValue {
533    #[tag("Number")]
534    Number(Number),
535    #[tag("Dimension")]
536    Dimension(Dimension),
537    #[tag("Percentage")]
538    Percentage(Percentage),
539    #[tag("Ident")]
540    Constant(Ident),
541    #[tag("CalcSum")]
542    Sum(CalcSum),
543    #[tag("Function")]
544    Function(Function),
545}
546
547#[ast_node]
548#[derive(Eq, Hash, Is, EqIgnoreSpan)]
549pub enum FamilyName {
550    #[tag("Str")]
551    Str(Str),
552    #[tag("SequenceOfCustomIdents")]
553    SequenceOfCustomIdents(SequenceOfCustomIdents),
554}
555
556#[ast_node("SequenceOfCustomIdents")]
557#[derive(Eq, Hash, EqIgnoreSpan)]
558pub struct SequenceOfCustomIdents {
559    pub span: Span,
560    pub value: Vec<CustomIdent>,
561}