1use crate::diagnostics;
2use css_parse::{Cursor, Parse, Parser, Result as ParserResult, T};
3use csskit_derives::{ToCursors, ToSpan, Visitable};
4
5#[derive(ToSpan, ToCursors, Visitable, Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
8#[cfg_attr(feature = "css_feature_data", derive(::csskit_derives::ToCSSFeature), css_feature("css.at-rules.charset"))]
9#[visit(self)]
10pub struct CharsetRule {
11 at_keyword: T![AtKeyword],
12 space: T![' '],
13 string: T![String],
14 semicolon: Option<T![;]>,
15}
16
17impl<'a> Parse<'a> for CharsetRule {
20 fn parse(p: &mut Parser<'a>) -> ParserResult<Self> {
21 let at_keyword = p.parse::<T![AtKeyword]>()?;
22 let c: Cursor = at_keyword.into();
23 if !p.eq_ignore_ascii_case(c, "charset") {
26 Err(diagnostics::UnexpectedAtRule(p.parse_str(c).into(), c))?;
27 }
28 let space = p.parse::<T![' ']>()?;
32 let string = p.parse::<T![String]>()?;
33 let semicolon = p.parse::<T![;]>().ok();
35 Ok(Self { at_keyword, space, string, semicolon })
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42 use css_parse::assert_parse;
43
44 #[test]
45 fn size_test() {
46 assert_eq!(std::mem::size_of::<CharsetRule>(), 52);
47 }
48
49 #[test]
50 fn test_writes() {
51 assert_parse!(CharsetRule, "@charset \"utf-8\";", "@charset \"utf-8\";");
52 assert_parse!(CharsetRule, "@charset \"UTF-8\";", "@charset \"UTF-8\";");
53 }
54}