1use std::hash::{Hash, Hasher};
2
3use is_macro::Is;
4#[cfg(feature = "serde-impl")]
5use serde::{Deserialize, Serialize};
6use swc_atoms::Atom;
7use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
8
9#[ast_node("PreservedToken")]
10#[derive(Eq, Hash, EqIgnoreSpan)]
11pub struct TokenAndSpan {
12 pub span: Span,
13 pub token: Token,
14}
15
16impl Take for TokenAndSpan {
17 fn dummy() -> Self {
18 Self {
19 span: Take::dummy(),
20 token: Take::dummy(),
21 }
22 }
23}
24
25#[derive(Debug, Clone, PartialEq, EqIgnoreSpan, Hash)]
26#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
27#[cfg_attr(
28 any(feature = "rkyv-impl"),
29 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
30)]
31#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))]
32#[cfg_attr(feature = "rkyv-impl", repr(C))]
33#[cfg_attr(
34 feature = "encoding-impl",
35 derive(::swc_common::Encode, ::swc_common::Decode)
36)]
37pub struct UrlKeyValue(pub Atom, pub Atom);
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Is, EqIgnoreSpan)]
40#[cfg_attr(
41 feature = "rkyv",
42 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
43)]
44#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
45#[cfg_attr(feature = "rkyv", repr(u32))]
46#[cfg_attr(
47 feature = "rkyv",
48 rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
49 __S::Error: rkyv::rancor::Source))
50)]
51#[cfg_attr(feature = "serde-impl", derive(Serialize, Deserialize))]
52#[cfg_attr(
53 feature = "encoding-impl",
54 derive(::swc_common::Encode, ::swc_common::Decode)
55)]
56pub enum NumberType {
57 #[cfg_attr(feature = "serde-impl", serde(rename = "integer"))]
58 Integer,
59 #[cfg_attr(feature = "serde-impl", serde(rename = "number"))]
60 Number,
61}
62
63#[derive(Debug, Clone, PartialEq, EqIgnoreSpan)]
64#[cfg_attr(
65 feature = "rkyv",
66 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
67)]
68#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
69#[cfg_attr(feature = "rkyv", repr(C))]
70#[cfg_attr(feature = "serde-impl", derive(Serialize, Deserialize))]
71#[cfg_attr(
72 feature = "encoding-impl",
73 derive(::swc_common::Encode, ::swc_common::Decode)
74)]
75pub struct DimensionToken {
76 pub value: f64,
77 pub raw_value: Atom,
78
79 pub unit: Atom,
80
81 #[cfg_attr(feature = "serde-impl", serde(rename = "type"))]
82 pub type_flag: NumberType,
83 pub raw_unit: Atom,
84}
85
86#[derive(Debug, Clone, PartialEq, EqIgnoreSpan)]
87#[cfg_attr(
88 feature = "rkyv",
89 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
90)]
91#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
92#[cfg_attr(feature = "rkyv", repr(u32))]
93#[cfg_attr(
94 feature = "rkyv",
95 rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
96 __S::Error: rkyv::rancor::Source))
97)]
98#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
99#[cfg_attr(
100 feature = "encoding-impl",
101 derive(::swc_common::Encode, ::swc_common::Decode)
102)]
103pub enum Token {
104 Ident {
105 value: Atom,
106 raw: Atom,
107 },
108 Function {
109 value: Atom,
110 raw: Atom,
111 },
112 AtKeyword {
114 value: Atom,
115 raw: Atom,
116 },
117 Hash {
119 is_id: bool,
120
121 value: Atom,
122 raw: Atom,
123 },
124 String {
125 value: Atom,
126 raw: Atom,
127 },
128 BadString {
129 raw: Atom,
130 },
131 Url {
133 value: Atom,
134 raw: Box<UrlKeyValue>,
136 },
137 BadUrl {
138 raw: Atom,
139 },
140 Delim {
141 #[cfg_attr(
142 feature = "encoding-impl",
143 encoding(with = "::swc_common::serializer::WithChar")
144 )]
145 value: char,
146 },
147 Number {
148 value: f64,
149 raw: Atom,
150 #[cfg_attr(feature = "serde-impl", serde(rename = "type"))]
151 type_flag: NumberType,
152 },
153 Percentage {
154 value: f64,
155 raw: Atom,
156 },
157 Dimension {
158 dimension: Box<DimensionToken>,
159 },
160 WhiteSpace {
162 value: Atom,
163 },
164 CDO,
166 CDC,
168 Colon,
170 Semi,
172 Comma,
174 LBracket,
176 RBracket,
178 LParen,
180 RParen,
182 LBrace,
184 RBrace,
186}
187
188impl Take for Token {
189 fn dummy() -> Self {
190 Self::Semi
191 }
192}
193
194#[allow(clippy::derived_hash_with_manual_eq)]
195#[allow(clippy::transmute_float_to_int)]
196impl Hash for Token {
197 fn hash<H: Hasher>(&self, state: &mut H) {
198 fn integer_decode(val: f64) -> (u64, i16, i8) {
199 let bits: u64 = f64::to_bits(val);
200 let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
201 let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
202 let mantissa = if exponent == 0 {
203 (bits & 0xfffffffffffff) << 1
204 } else {
205 (bits & 0xfffffffffffff) | 0x10000000000000
206 };
207
208 exponent -= 1023 + 52;
209 (mantissa, exponent, sign)
210 }
211
212 match self {
213 Token::Ident { value, raw } => {
214 value.hash(state);
215 raw.hash(state);
216 }
217 Token::Function { value, raw } => {
218 value.hash(state);
219 raw.hash(state);
220 }
221 Token::AtKeyword { value, raw } => {
222 value.hash(state);
223 raw.hash(state);
224 }
225 Token::String { value, raw } => {
226 value.hash(state);
227 raw.hash(state);
228 }
229 Token::BadString { raw } => {
230 raw.hash(state);
231 }
232 Token::Hash { value, raw, is_id } => {
233 value.hash(state);
234 raw.hash(state);
235 is_id.hash(state);
236 }
237 Token::Url { value, raw } => {
238 value.hash(state);
239 raw.hash(state);
240 }
241 Token::BadUrl { raw, .. } => {
242 raw.hash(state);
243 }
244 Token::Delim { value } => {
245 value.hash(state);
246 }
247 Token::Number {
248 value,
249 raw,
250 type_flag,
251 } => {
252 integer_decode(*value).hash(state);
253 raw.hash(state);
254 type_flag.hash(state);
255 }
256 Token::Percentage { value, raw } => {
257 integer_decode(*value).hash(state);
258 raw.hash(state);
259 }
260 Token::Dimension { dimension } => {
261 integer_decode(dimension.value).hash(state);
262 dimension.unit.hash(state);
263 dimension.type_flag.hash(state);
264 dimension.raw_value.hash(state);
265 dimension.raw_unit.hash(state);
266 }
267 Token::WhiteSpace { value, .. } => {
268 value.hash(state);
269 }
270 Token::CDO
271 | Token::CDC
272 | Token::Colon
273 | Token::Semi
274 | Token::Comma
275 | Token::LBracket
276 | Token::RBracket
277 | Token::LParen
278 | Token::RParen
279 | Token::LBrace
280 | Token::RBrace => {}
281 }
282 }
283}
284
285impl Eq for Token {}