css_lexer/kind.rs
1use core::fmt;
2
3use crate::KindSet;
4
5/// Kind represents the token "Type", categorised mostly by the token types within the CSS Syntax spec.
6///
7/// Maintaining parity with the spec makes it easier to reason about logica round the parser, despite it being possible to
8/// group a bunch of these tokens into a single "delimiter" token.
9///
10/// Importantly, `Kind` is represented as `u8` and must only use the 5 low bits, because the upper 3 bits get used to
11/// house details about each kind, that a token would be interested in learning about.
12#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum Kind {
14 // Trivias (mask as 0b0_00XX)
15 /// Represents the [<eof-token>][1] defined in CSS. While CSS stipulates that this token is never produced by a
16 /// tokenizer, this [Lexer][crate::Lexer] _will_ produce [<eof-token>s][1] if the underlying source has been
17 /// fully consumed.
18 ///
19 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-eof-token
20 Eof = 0b0000,
21
22 /// Represents the [<whitespace-token>][1] defined in CSS.
23 ///
24 /// ```md
25 /// <newline>
26 /// │├──╮─ "\n" ───╭──┤│
27 /// ├─ "\r\n" ─┤
28 /// ├─ "\r" ───┤
29 /// ╰─ "\f" ───╯
30 ///
31 /// <whitespace>
32 /// │├──╮─ " " ───────╭──┤│
33 /// ├─ "\t" ──────┤
34 /// ╰─ <newline> ─╯
35 ///
36 /// <whitespace-token>
37 /// │├─╭─ <whitespace> ─╮─┤│
38 /// ╰────────────────╯
39 /// ```
40 ///
41 /// While CSS stipulates that this token represents collapsed whitespace, it is possible for [Lexer][crate::Lexer]
42 /// to produce multiple consecutive [Kind::Whitespace] tokens if the
43 /// [Feature::SeparateWhitespace][crate::Feature::SeparateWhitespace] runtime feature is enabled. In this case,
44 /// `<whitespace-token>` becomes:
45 ///
46 /// ```md
47 /// <whitespace-token>
48 /// │├──╮─╭─ " " ───────╮─╭──┤│
49 /// │ ╰─────────────╯ │
50 /// ├─╭─ "\t" ──────╮─┤
51 /// │ ╰─────────────╯ │
52 /// ╰─╭─ <newline> ─╮─╯
53 /// ╰─────────────╯
54 /// ```
55 ///
56 /// [1]: https://drafts.csswg.org/css-syntax/#whitespace-token-diagram
57 #[default]
58 Whitespace = 0b0001,
59
60 /// Represents the [<comment>][1] defined in CSS. While CSS stipulates comment tokens are not produced during
61 /// tokenization, they are for this [Lexer][crate::Lexer] as they're needed in order to preserve them.
62 ///
63 /// ```md
64 /// <comment>
65 /// ╭──────────────────────────────────────────╮
66 /// │├─ "/*" ─╯-╭─ (anything but "*" followed by "/") ─╮─╰─ "*/" ─┤│
67 /// ╰──────────────────────────────────────╯
68 /// ```
69 ///
70 /// It is possible for [Lexer][crate::Lexer] to produce [Kind::Whitespace] tokens that begin `//` if the
71 /// [Feature::SingleLineComments][crate::Feature::SingleLineComments] runtime feature is enabled. In this mode,
72 /// `<comment>` becomes:
73 ///
74 /// ```md
75 /// <comment>
76 /// ╭──────────────────────────────────────────╮
77 /// │├──╮─ "/*" ─╯-╭─ (anything but "*" followed by "/") ─╮─╰─ "*/" ─╭─┤│
78 /// │ ╰──────────────────────────────────────╯ │
79 /// │ ╭───────────────────────────╮ │
80 /// ╰─ "//" ───────╯-╭─ (anything but "\n") ─╮─╰─ "\n" ──────────╯
81 /// ╰───────────────────────╯
82 /// ```
83 ///
84 /// [1]: https://drafts.csswg.org/css-syntax/#comment-diagram
85 Comment = 0b0010,
86
87 /// Represents both the [<cdc-token>][1] and [<cdo-token>][2]s defined in CSS. While CSS separates these tokens,
88 /// they're only useful representations at the top-level stylesheet, anywhere else they represent a parse error, and
89 /// it's a little pointless to define two tokens types for what amounts to a parse error.
90 ///
91 /// ```md
92 /// <cdo-token>
93 /// │├─ "<!--" ─┤│
94 ///
95 /// <cdc-token>
96 /// │├─ "-->" ─┤│
97 ///
98 /// <cdc-or-cdo-token> (Not part of the CSS specification)
99 /// │├──╮─ <cdo-token> ─╭──┤│
100 /// ╰─ <crc-token> ─╯
101 /// ```
102 ///
103 /// [1]: https://drafts.csswg.org/css-syntax/#CDC-token-diagram
104 /// [2]: https://drafts.csswg.org/css-syntax/#CDO-token-diagram
105 CdcOrCdo = 0b0011,
106
107 // Numerics (mask as 0b0_010X)
108 /// Represents the [<number-token>][1].
109 ///
110 /// ```md
111 ///
112 /// <number-token>
113 /// ╭─ "+" ─╮
114 /// │├─├───────┤───╭─ [digit] ─╮─ "." ─╭─ [digit] ─╮──╭───╮──────────────────────────────────╭──┤│
115 /// ╰─ "-" ─╯ │ ╰───────────╯ ╰───────────╯ │ │ ╭─ "+" ─╮ │
116 /// ├───────── ╭─ [digit] ─╮─────────────┤ ├─ "e" ─╭─├───────┤──╭─ [digit] ─╮─╯
117 /// │ ╰───────────╯ │ ╰─ "E" ─╯ ╰─ "-" ─╯ ╰───────────╯
118 /// ╰──── "." ─╭─ [digit] ─╮─────────────╯
119 /// ╰───────────╯
120 /// ```
121 ///
122 /// [1]: https://drafts.csswg.org/css-syntax/#number-token-diagram
123 Number = 0b0100,
124
125 /// Represents the [<dimension-token>][1].
126 ///
127 /// Here we deviate from the spec slightly, which has both [<dimension-token>][1] and [<percentage-token>][2].
128 /// `<percentage-token>` represents a dimension with a `%` symbol, but having this as a separate token results in more
129 /// work in the parser for little gain in the Lexer. So instead this lexer does not have a `<percentage-token>` and
130 /// instead folds the grammar for it inside of `<dimension-token>`.
131 ///
132 /// ```md
133 ///
134 /// <newline>
135 /// │├──╮─ "\n" ───╭──┤│
136 /// ├─ "\r\n" ─┤
137 /// ├─ "\r" ───┤
138 /// ╰─ "\f" ───╯
139 ///
140 /// <whitespace>
141 /// │├──╮─ " " ───────╭──┤│
142 /// ├─ "\t" ──────┤
143 /// ╰─ <newline> ─╯
144 ///
145 /// <hexdigit>
146 /// │├─ [ 0-9, A-F, a-f ] ─┤│
147 ///
148 ///
149 /// <escape>
150 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
151 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
152 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
153 ///
154 /// <ident-token>
155 /// ╭───────────────── "--" ─────────────────────╮ ╭───────────────────────────────────────────╮
156 /// │├─╯─╮───────╭─╮─ [a-z, A-Z, "_", non-ASCII] ─╭─╰──╯─╭─╮─ [a-z, A-Z, 0-9, "_", non-ASCII] ─╭─╮─╰──┤│
157 /// ╰─ "-" ─╯ ╰──────── <escape> ────────────╯ │ ╰──────────── <escape> ─────────────╯ │
158 /// ╰───────────────────────────────────────╯
159 ///
160 /// <number-token>
161 /// ╭─ "+" ─╮
162 /// │├─├───────┤─╮─╭─ [digit] ─╮─ "." ─╭─ [digit] ─╮──╭───╮──────────────────────────────────╭──┤│
163 /// ╰─ "-" ─╯ │ ╰───────────╯ ╰───────────╯ │ │ ╭─ "+" ─╮ │
164 /// ├───────── ╭─ [digit] ─╮─────────────┤ ├─ "e" ─╭─├───────┤──╭─ [digit] ─╮─╯
165 /// │ ╰───────────╯ │ ╰─ "E" ─╯ ╰─ "-" ─╯ ╰───────────╯
166 /// ╰──── "." ─╭─ [digit] ─╮─────────────╯
167 /// ╰───────────╯
168 ///
169 /// <dimension-token>
170 /// │├─ <number-token> ─ <ident-token> ─┤│
171 ///
172 /// ```
173 ///
174 /// ```md
175 ///
176 /// <dimension-token> // Refined for this lexer, not true to the standard.
177 /// │├─ <number-token> ─╮─ <ident-token> ─╭──┤│
178 /// ╰────── "%" ──────╯
179 /// ```
180 ///
181 /// [1]: https://drafts.csswg.org/css-syntax/#dimension-token-diagram
182 /// [2]: https://drafts.csswg.org/css-syntax/#percentage-token-diagram
183 Dimension = 0b0101,
184
185 // Errors (mask as 0b0_011X)
186 /// Represents the [<bad-string-token>][1]. This token is a failure to fully lex the [<string-token>][2].
187 ///
188 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-bad-string-token
189 /// [2]: https://drafts.csswg.org/css-syntax/#typedef-string-token
190 BadString = 0b0110,
191
192 /// Represents the [<bad-url-token>][1]. This token is a failure to fully lex the [<url-token>][2].
193 ///
194 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-bad-url-token
195 /// [2]: https://drafts.csswg.org/css-syntax/#typedef-url-token
196 BadUrl = 0b0111,
197
198 // Variable length Ident-like Tokens (mask: 0b0_1XXX)
199 /// Represents the [<ident-token>][1].
200 ///
201 /// ```md
202 ///
203 /// <newline>
204 /// │├──╮─ "\n" ───╭──┤│
205 /// ├─ "\r\n" ─┤
206 /// ├─ "\r" ───┤
207 /// ╰─ "\f" ───╯
208 ///
209 /// <whitespace>
210 /// │├──╮─ " " ─────╭──┤│
211 /// ├─ "\t" ────┤
212 /// ╰─ newline ─╯
213 ///
214 /// <hexdigit>
215 /// │├─ [ 0-9, A-F, a-f ] ─┤│
216 ///
217 ///
218 /// <escape>
219 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
220 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
221 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
222 ///
223 /// <ident-token>
224 /// ╭───────────────── "--" ─────────────────────╮ ╭───────────────────────────────────────────╮
225 /// │├─╯─╮───────╭─╮─ [a-z, A-Z, "_", non-ASCII] ─╭─╰──╯─╭─╮─ [a-z, A-Z, 0-9, "_", non-ASCII] ─╭─╮─╰──┤│
226 /// ╰─ "-" ─╯ ╰──────── <escape> ────────────╯ │ ╰──────────── <escape> ─────────────╯ │
227 /// ╰───────────────────────────────────────╯
228 ///
229 /// ```
230 ///
231 /// [1]: https://drafts.csswg.org/css-syntax/#ident-token-diagram
232 Ident = 0b1000,
233
234 /// Represents the [<function-token>][1].
235 ///
236 /// ```md
237 ///
238 /// <newline>
239 /// │├──╮─ "\n" ───╭──┤│
240 /// ├─ "\r\n" ─┤
241 /// ├─ "\r" ───┤
242 /// ╰─ "\f" ───╯
243 ///
244 /// <whitespace>
245 /// │├──╮─ " " ───────╭──┤│
246 /// ├─ "\t" ──────┤
247 /// ╰─ <newline> ─╯
248 ///
249 /// <hexdigit>
250 /// │├─ [ 0-9, A-F, a-f ] ─┤│
251 ///
252 ///
253 /// <escape>
254 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
255 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
256 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
257 ///
258 /// <ident-token>
259 /// ╭───────────────── "--" ─────────────────────╮ ╭───────────────────────────────────────────╮
260 /// │├─╯─╮───────╭─╮─ [a-z, A-Z, "_", non-ASCII] ─╭─╰──╯─╭─╮─ [a-z, A-Z, 0-9, "_", non-ASCII] ─╭─╮─╰──┤│
261 /// ╰─ "-" ─╯ ╰──────── <escape> ────────────╯ │ ╰──────────── <escape> ─────────────╯ │
262 /// ╰───────────────────────────────────────╯
263 ///
264 /// <function-token>
265 /// │├─ <ident-token> ─ "(" ─┤│
266 ///
267 /// ```
268 ///
269 /// [1]: https://drafts.csswg.org/css-syntax/#function-token-diagram
270 Function = 0b1001,
271
272 /// Represents the [<at-keyword-token>][1].
273 ///
274 /// ```md
275 ///
276 /// <newline>
277 /// │├──╮─ "\n" ───╭──┤│
278 /// ├─ "\r\n" ─┤
279 /// ├─ "\r" ───┤
280 /// ╰─ "\f" ───╯
281 ///
282 /// <whitespace>
283 /// │├──╮─ " " ───────╭──┤│
284 /// ├─ "\t" ──────┤
285 /// ╰─ <newline> ─╯
286 ///
287 /// <hexdigit>
288 /// │├─ [ 0-9, A-F, a-f ] ─┤│
289 ///
290 ///
291 /// <escape>
292 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
293 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
294 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
295 ///
296 /// <ident-token>
297 /// ╭───────────────── "--" ─────────────────────╮ ╭───────────────────────────────────────────╮
298 /// │├─╯─╮───────╭─╮─ [a-z, A-Z, "_", non-ASCII] ─╭─╰──╯─╭─╮─ [a-z, A-Z, 0-9, "_", non-ASCII] ─╭─╮─╰──┤│
299 /// ╰─ "-" ─╯ ╰──────── <escape> ────────────╯ │ ╰──────────── <escape> ─────────────╯ │
300 /// ╰───────────────────────────────────────╯
301 ///
302 /// <at-keyword-token>
303 /// │├─ "@" ─ <ident-token> ─┤│
304 ///
305 /// ```
306 ///
307 /// [1]: https://drafts.csswg.org/css-syntax/#hash-token-diagram
308 AtKeyword = 0b1010,
309
310 /// Represents the [<hash-token>][1].
311 ///
312 /// ```md
313 ///
314 /// <newline>
315 /// │├──╮─ "\n" ───╭──┤│
316 /// ├─ "\r\n" ─┤
317 /// ├─ "\r" ───┤
318 /// ╰─ "\f" ───╯
319 ///
320 /// <whitespace>
321 /// │├──╮─ " " ───────╭──┤│
322 /// ├─ "\t" ──────┤
323 /// ╰─ <newline> ─╯
324 ///
325 /// <hexdigit>
326 /// │├─ [ 0-9, A-F, a-f ] ─┤│
327 ///
328 ///
329 /// <escape>
330 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
331 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
332 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
333 ///
334 /// <hash-token>
335 /// │├─ "#" ──╭─╮─ [a-z, A-Z, 0-9, "_", "-", non-ASCII] ─╭─╮─┤│
336 /// │ ╰─────────────── <escape> ───────────────╯ │
337 /// ╰────────────────────────────────────────────╯
338 ///
339 /// ```
340 ///
341 /// [1]: https://drafts.csswg.org/css-syntax/#at-keyword-token-diagram
342 Hash = 0b1011,
343
344 /// Represents the [<string-token>][1].
345 ///
346 /// ```md
347 ///
348 /// <newline>
349 /// │├──╮─ "\n" ───╭──┤│
350 /// ├─ "\r\n" ─┤
351 /// ├─ "\r" ───┤
352 /// ╰─ "\f" ───╯
353 ///
354 /// <escape>
355 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
356 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
357 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
358 ///
359 /// <string-token>
360 /// ╭───────────────────────────────────╮
361 /// │├─╮─ """ ─╯─╭─╮─ [not """, "\", newline] ─╭─╮─╰── """ ─╭─┤│
362 /// │ │ ├──────── <escape> ─────────┤ │ │
363 /// │ │ ╰───── "\" ─ <newline> ─────╯ │ │
364 /// │ ╰───────────────────────────────╯ │
365 /// │ ╭───────────────────────────────────╮ │
366 /// ╰─ "'" ─╯─╭─╮─ [not """, "\", newline] ─╭─╮─╰── "'" ─╯
367 /// │ ├──────── <escape> ─────────┤ │
368 /// │ ╰───── "\" ─ <newline> ─────╯ │
369 /// ╰───────────────────────────────╯
370 ///
371 /// ```
372 ///
373 /// [1]: https://drafts.csswg.org/css-syntax/#string-token-diagram
374 String = 0b1100,
375
376 /// Represents the [<url-token>][1].
377 ///
378 /// ```md
379 ///
380 /// <newline>
381 /// │├──╮─ "\n" ───╭──┤│
382 /// ├─ "\r\n" ─┤
383 /// ├─ "\r" ───┤
384 /// ╰─ "\f" ───╯
385 ///
386 /// <whitespace>
387 /// │├──╮─ " " ───────╭──┤│
388 /// ├─ "\t" ──────┤
389 /// ╰─ <newline> ─╯
390 ///
391 /// <whitespace-token>
392 /// │├─╭─ <whitespace> ─╮─┤│
393 /// ╰────────────────╯
394 ///
395 /// <ws*>
396 /// ╭──────────────────────────╮
397 /// │├─╯─╭─ <whitespace-token> ─╮─╰─┤│
398 /// ╰──────────────────────╯
399 ///
400 /// <hexdigit>
401 /// │├─ [ 0-9, A-F, a-f ] ─┤│
402 ///
403 ///
404 /// <escape>
405 /// │├─ "\" ─╮───── [not <newline> or <hexdigit>] ───╭─┤│
406 /// ╰─╭── <hexdigit> ─╮──╮────────────────╭─╯
407 /// ╰─ (1-6 times) ─╯ ╰─ <whitespace> ─╯
408 ///
409 /// <ident-token>
410 /// ╭───────────────── "--" ─────────────────────╮ ╭───────────────────────────────────────────╮
411 /// │├─╯─╮───────╭─╮─ [a-z, A-Z, "_", non-ASCII] ─╭─╰──╯─╭─╮─ [a-z, A-Z, 0-9, "_", non-ASCII] ─╭─╮─╰──┤│
412 /// ╰─ "-" ─╯ ╰──────── <escape> ────────────╯ │ ╰──────────── <escape> ─────────────╯ │
413 /// ╰───────────────────────────────────────╯
414 ///
415 /// <url-token>
416 /// ╭───────────────────────────────────────────────────────────────────╮
417 /// │├─ <ident-token "url"> ─ "(" ─ <ws*> ─╯─╭─╮─ [not """ "'" "(" ")" "\" <whitespace> or non-printable] ─╭─╮─╰─ <ws*> ─ ")" ─┤│
418 /// │ ╰──────────────────────── <escape> ─────────────────────────╯ │
419 /// ╰───────────────────────────────────────────────────────────────╯
420 ///
421 /// ```
422 ///
423 /// [1]: https://drafts.csswg.org/css-syntax/#url-token-diagram
424 Url = 0b1101,
425
426 // Single character Tokens (mask 0b1_XXXX)
427 /// Represents the [<delim-token>][1]. The `<delim-token>` has a value composed of a single code point.
428 ///
429 /// ```md
430 /// <delim-token>
431 /// │├─ [codepoint] ─┤│
432 /// ```
433 ///
434 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-delim-token
435 Delim = 0b1_0000,
436
437 /// Represents the [<colon-token>][1].
438 ///
439 /// ```md
440 /// <colon-token>
441 /// │├─ ":" ─┤│
442 /// ```
443 ///
444 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-colon-token
445 Colon = 0b1_0001,
446
447 /// Represents the [<semicolon-token>][1].
448 ///
449 /// ```md
450 /// <semicolon-token>
451 /// │├─ ";" ─┤│
452 /// ```
453 ///
454 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-semicolon-token
455 Semicolon = 0b1_0010,
456
457 /// Represents the [<comma-token>][1].
458 ///
459 /// ```md
460 /// <comma-token>
461 /// │├─ "," ─┤│
462 /// ```
463 ///
464 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-comma-token
465 Comma = 0b1_0011,
466
467 /// Represents the [<\[-token>][1].
468 ///
469 /// ```md
470 /// <[-token>
471 /// │├─ "[" ─┤│
472 /// ```
473 ///
474 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-open-square
475 LeftSquare = 0b1_0100,
476
477 /// Represents the [<\]-token>][1].
478 ///
479 /// ```md
480 /// <]-token>
481 /// │├─ "]" ─┤│
482 /// ```
483 ///
484 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-close-square
485 RightSquare = 0b1_0101,
486
487 /// Represents the [<(-token>][1].
488 ///
489 /// ```md
490 /// <(-token>
491 /// │├─ "(" ─┤│
492 /// ```
493 ///
494 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-open-paren
495 LeftParen = 0b1_0110,
496
497 /// Represents the [<)-token>][1].
498 ///
499 /// ```md
500 /// <)-token>
501 /// │├─ ")" ─┤│
502 /// ```
503 ///
504 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-close-paren
505 RightParen = 0b1_0111,
506
507 /// Represents the [<{-token>][1].
508 ///
509 /// ```md
510 /// <{-token>
511 /// │├─ "{" ─┤│
512 /// ```
513 ///
514 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-open-curly
515 LeftCurly = 0b1_1000,
516
517 /// Represents the [<}-token>][1].
518 ///
519 /// ```md
520 /// <}-token>
521 /// │├─ "}" ─┤│
522 /// ```
523 ///
524 /// [1]: https://drafts.csswg.org/css-syntax/#typedef-close-curly
525 RightCurly = 0b1_1001,
526}
527
528impl Kind {
529 pub(crate) const fn from_bits(bits: u8) -> Self {
530 match bits {
531 0b0001 => Self::Whitespace,
532 0b0010 => Self::Comment,
533 0b0011 => Self::CdcOrCdo,
534 0b0100 => Self::Number,
535 0b0101 => Self::Dimension,
536 0b0110 => Self::BadString,
537 0b0111 => Self::BadUrl,
538 0b1000 => Self::Ident,
539 0b1001 => Self::Function,
540 0b1010 => Self::AtKeyword,
541 0b1011 => Self::Hash,
542 0b1100 => Self::String,
543 0b1101 => Self::Url,
544 0b1_0000 => Self::Delim,
545 0b1_0001 => Self::Colon,
546 0b1_0010 => Self::Semicolon,
547 0b1_0011 => Self::Comma,
548 0b1_0100 => Self::LeftSquare,
549 0b1_0101 => Self::RightSquare,
550 0b1_0110 => Self::LeftParen,
551 0b1_0111 => Self::RightParen,
552 0b1_1000 => Self::LeftCurly,
553 0b1_1001 => Self::RightCurly,
554 _ => Self::Eof,
555 }
556 }
557
558 #[doc(hidden)]
559 pub const fn as_str(&self) -> &str {
560 match *self {
561 Kind::Eof => "Eof",
562 Kind::Whitespace => "Whitespace",
563 Kind::Comment => "Comment",
564 Kind::CdcOrCdo => "CdcOrCdo",
565 Kind::Number => "Number",
566 Kind::Dimension => "Dimension",
567 Kind::BadString => "BadString",
568 Kind::BadUrl => "BadUrl",
569 Kind::Ident => "Ident",
570 Kind::Function => "Function",
571 Kind::AtKeyword => "AtKeyword",
572 Kind::Hash => "Hash",
573 Kind::String => "String",
574 Kind::Url => "Url",
575 Kind::Delim => "Delim",
576 Kind::Colon => "Colon",
577 Kind::Semicolon => "Semicolon",
578 Kind::Comma => "Comma",
579 Kind::LeftSquare => "LeftSquare",
580 Kind::RightSquare => "RightSquare",
581 Kind::LeftParen => "LeftParen",
582 Kind::RightParen => "RightParen",
583 Kind::LeftCurly => "LeftCurly",
584 Kind::RightCurly => "RightCurly",
585 }
586 }
587}
588
589impl fmt::Debug for Kind {
590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
591 write!(f, "Kind::{}", self.as_str())
592 }
593}
594
595impl fmt::Display for Kind {
596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597 write!(f, "Kind::{}", self.as_str())
598 }
599}
600
601impl PartialEq<KindSet> for Kind {
602 fn eq(&self, other: &KindSet) -> bool {
603 other.contains_bits(*self as u8)
604 }
605}
606
607#[test]
608fn test_from_bits() {
609 assert_eq!(Kind::from_bits(Kind::Eof as u8), Kind::Eof);
610 assert_eq!(Kind::from_bits(Kind::Whitespace as u8), Kind::Whitespace);
611 assert_eq!(Kind::from_bits(Kind::Comment as u8), Kind::Comment);
612 assert_eq!(Kind::from_bits(Kind::CdcOrCdo as u8), Kind::CdcOrCdo);
613 assert_eq!(Kind::from_bits(Kind::Number as u8), Kind::Number);
614 assert_eq!(Kind::from_bits(Kind::Dimension as u8), Kind::Dimension);
615 assert_eq!(Kind::from_bits(Kind::BadString as u8), Kind::BadString);
616 assert_eq!(Kind::from_bits(Kind::BadUrl as u8), Kind::BadUrl);
617 assert_eq!(Kind::from_bits(Kind::Ident as u8), Kind::Ident);
618 assert_eq!(Kind::from_bits(Kind::Function as u8), Kind::Function);
619 assert_eq!(Kind::from_bits(Kind::AtKeyword as u8), Kind::AtKeyword);
620 assert_eq!(Kind::from_bits(Kind::Hash as u8), Kind::Hash);
621 assert_eq!(Kind::from_bits(Kind::String as u8), Kind::String);
622 assert_eq!(Kind::from_bits(Kind::Url as u8), Kind::Url);
623 assert_eq!(Kind::from_bits(Kind::Delim as u8), Kind::Delim);
624 assert_eq!(Kind::from_bits(Kind::Colon as u8), Kind::Colon);
625 assert_eq!(Kind::from_bits(Kind::Semicolon as u8), Kind::Semicolon);
626 assert_eq!(Kind::from_bits(Kind::Comma as u8), Kind::Comma);
627 assert_eq!(Kind::from_bits(Kind::LeftSquare as u8), Kind::LeftSquare);
628 assert_eq!(Kind::from_bits(Kind::RightSquare as u8), Kind::RightSquare);
629 assert_eq!(Kind::from_bits(Kind::LeftParen as u8), Kind::LeftParen);
630 assert_eq!(Kind::from_bits(Kind::RightParen as u8), Kind::RightParen);
631 assert_eq!(Kind::from_bits(Kind::LeftCurly as u8), Kind::LeftCurly);
632 assert_eq!(Kind::from_bits(Kind::RightCurly as u8), Kind::RightCurly);
633}
634
635#[test]
636fn size_test() {
637 assert_eq!(::std::mem::size_of::<Kind>(), 1);
638}