1use cssparser::ParserState;
2
3pub(crate) struct CSSRuleListParser<'d, 'i>(&'d mut Vec<Declaration<'i>>);
4
5impl<'d, 'i> CSSRuleListParser<'d, 'i> {
6 #[inline]
7 pub(crate) fn new(declarations: &'d mut Vec<Declaration<'i>>) -> CSSRuleListParser<'d, 'i> {
8 CSSRuleListParser(declarations)
9 }
10}
11
12pub(crate) struct CSSDeclarationListParser;
13
14pub(crate) type Name<'i> = cssparser::CowRcStr<'i>;
15pub(crate) type Declaration<'i> = (Name<'i>, &'i str);
16pub(crate) type QualifiedRule<'i> = (&'i str, (usize, usize));
17
18fn exhaust<'i>(input: &mut cssparser::Parser<'i, '_>) -> &'i str {
19 let start = input.position();
20 while input.next().is_ok() {}
21 input.slice_from(start)
22}
23
24impl<'i> cssparser::QualifiedRuleParser<'i> for CSSRuleListParser<'_, 'i> {
28 type Prelude = &'i str;
29 type QualifiedRule = QualifiedRule<'i>;
30 type Error = ();
31
32 fn parse_prelude<'t>(
33 &mut self,
34 input: &mut cssparser::Parser<'i, 't>,
35 ) -> Result<Self::Prelude, cssparser::ParseError<'i, Self::Error>> {
36 Ok(exhaust(input))
38 }
39
40 fn parse_block<'t>(
41 &mut self,
42 prelude: Self::Prelude,
43 _: &ParserState,
44 input: &mut cssparser::Parser<'i, 't>,
45 ) -> Result<Self::QualifiedRule, cssparser::ParseError<'i, Self::Error>> {
46 Ok((prelude, parse_declarations_into(input, self.0)))
47 }
48}
49
50impl<'i> cssparser::DeclarationParser<'i> for CSSDeclarationListParser {
52 type Declaration = Declaration<'i>;
53 type Error = ();
54
55 fn parse_value<'t>(
56 &mut self,
57 name: Name<'i>,
58 input: &mut cssparser::Parser<'i, 't>,
59 _declaration_start: &ParserState,
60 ) -> Result<Self::Declaration, cssparser::ParseError<'i, Self::Error>> {
61 Ok((name, exhaust(input)))
62 }
63}
64
65impl<'i> cssparser::AtRuleParser<'i> for CSSRuleListParser<'_, 'i> {
66 type Prelude = &'i str;
67 type AtRule = QualifiedRule<'i>;
68 type Error = ();
69}
70
71impl<'i> cssparser::AtRuleParser<'i> for CSSDeclarationListParser {
74 type Prelude = String;
75 type AtRule = Declaration<'i>;
76 type Error = ();
77}
78
79impl<'i> cssparser::RuleBodyItemParser<'i, Declaration<'i>, ()> for CSSDeclarationListParser {
80 fn parse_declarations(&self) -> bool {
81 true
82 }
83
84 fn parse_qualified(&self) -> bool {
85 true
86 }
87}
88
89impl<'i> cssparser::QualifiedRuleParser<'i> for CSSDeclarationListParser {
90 type Prelude = String;
91 type QualifiedRule = Declaration<'i>;
92 type Error = ();
93}
94
95pub(crate) struct AtRuleFilteringParser<'d, 'i, 'o> {
96 declarations: &'d mut Vec<Declaration<'i>>,
97 at_rules: &'o mut String,
98}
99
100impl<'d, 'i, 'o> AtRuleFilteringParser<'d, 'i, 'o> {
101 #[inline]
102 pub(crate) fn new(
103 declarations: &'d mut Vec<Declaration<'i>>,
104 at_rules: &'o mut String,
105 ) -> AtRuleFilteringParser<'d, 'i, 'o> {
106 AtRuleFilteringParser {
107 declarations,
108 at_rules,
109 }
110 }
111}
112
113impl<'i> cssparser::QualifiedRuleParser<'i> for AtRuleFilteringParser<'_, 'i, '_> {
114 type Prelude = &'i str;
115 type QualifiedRule = QualifiedRule<'i>;
116 type Error = ();
117
118 fn parse_prelude<'t>(
119 &mut self,
120 input: &mut cssparser::Parser<'i, 't>,
121 ) -> Result<Self::Prelude, cssparser::ParseError<'i, Self::Error>> {
122 Ok(exhaust(input))
123 }
124
125 fn parse_block<'t>(
126 &mut self,
127 prelude: Self::Prelude,
128 _: &ParserState,
129 input: &mut cssparser::Parser<'i, 't>,
130 ) -> Result<Self::QualifiedRule, cssparser::ParseError<'i, Self::Error>> {
131 Ok((prelude, parse_declarations_into(input, self.declarations)))
132 }
133}
134
135impl<'i> cssparser::AtRuleParser<'i> for AtRuleFilteringParser<'_, 'i, '_> {
136 type Prelude = &'i str;
137 type AtRule = QualifiedRule<'i>;
138 type Error = ();
139
140 fn parse_prelude<'t>(
141 &mut self,
142 name: cssparser::CowRcStr<'i>,
143 input: &mut cssparser::Parser<'i, 't>,
144 ) -> Result<Self::Prelude, cssparser::ParseError<'i, Self::Error>> {
145 self.at_rules.push('@');
146 self.at_rules.push_str(&name);
147 Ok(exhaust(input))
148 }
149
150 fn parse_block<'t>(
151 &mut self,
152 prelude: Self::Prelude,
153 _start: &ParserState,
154 input: &mut cssparser::Parser<'i, 't>,
155 ) -> Result<Self::AtRule, cssparser::ParseError<'i, Self::Error>> {
156 let start = self.at_rules.len();
157 self.at_rules.push_str(prelude);
158 self.at_rules.push('{');
159 self.at_rules.push_str(exhaust(input));
160 self.at_rules.push('}');
161 self.at_rules.push(' ');
162 Ok((prelude, (start, self.at_rules.len())))
163 }
164}
165
166fn parse_declarations_into<'i>(
167 input: &mut cssparser::Parser<'i, '_>,
168 declarations: &mut Vec<Declaration<'i>>,
169) -> (usize, usize) {
170 let mut parser = CSSDeclarationListParser;
171 let parser = cssparser::RuleBodyParser::new(input, &mut parser);
172 let start = declarations.len();
173 for item in parser.flatten() {
174 declarations.push(item);
175 }
176 (start, declarations.len())
177}