accessibility_tree/style/
declaration_block.rs

1use crate::style::errors::PropertyParseErrorKind;
2use crate::style::properties::{property_data_by_name, LonghandDeclaration, PerPhase, Phase};
3use crate::style::values::{CssWideKeyword, Parse};
4use cssparser::{AtRuleParser, ParseError, Parser};
5use cssparser::{CowRcStr, DeclarationListParser, DeclarationParser};
6use std::iter::repeat;
7
8impl std::fmt::Debug for LonghandDeclaration {
9    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
10        Ok(())
11    }
12}
13
14#[derive(Default, Debug)]
15pub struct DeclarationBlock {
16    declarations: Vec<LonghandDeclaration>,
17    important: smallbitvec::SmallBitVec,
18    any_important: PerPhase<bool>,
19    any_normal: PerPhase<bool>,
20}
21
22impl DeclarationBlock {
23    pub fn parse(parser: &mut Parser) -> Self {
24        let mut iter = DeclarationListParser::new(
25            parser,
26            LonghandDeclarationParser {
27                block: DeclarationBlock::default(),
28            },
29        );
30        loop {
31            let previous_len = iter.parser.block.declarations.len();
32            let result = if let Some(r) = iter.next() { r } else { break };
33            match result {
34                Ok(()) => {}
35                Err(_) => {
36                    // we may not want to break the loop - look into repaairing the parser.
37                    if iter.parser.block.declarations.len() == previous_len {
38                        // println!("Parse error prior block length exceeded.");
39                        break;
40                    }
41                }
42            }
43            debug_assert_eq!(
44                iter.parser.block.declarations.len(),
45                iter.parser.block.important.len()
46            );
47        }
48        debug_assert_eq!(
49            iter.parser.block.any_normal.early || iter.parser.block.any_normal.late,
50            !iter.parser.block.important.all_true()
51        );
52        debug_assert_eq!(
53            iter.parser.block.any_important.early || iter.parser.block.any_important.late,
54            !iter.parser.block.important.all_false()
55        );
56        iter.parser.block
57    }
58
59    pub fn cascade_normal(&self, phase: &mut impl Phase) {
60        self.cascade(false, self.any_normal, phase)
61    }
62
63    pub fn cascade_important(&self, phase: &mut impl Phase) {
64        self.cascade(true, self.any_important, phase)
65    }
66
67    fn cascade(&self, important: bool, any: PerPhase<bool>, phase: &mut impl Phase) {
68        if phase.select(any) {
69            self.declarations.iter().zip(&self.important).for_each(
70                move |(declaration, declaration_important)| {
71                    if declaration_important == important {
72                        phase.cascade(declaration)
73                    }
74                },
75            )
76        }
77    }
78}
79
80struct LonghandDeclarationParser {
81    block: DeclarationBlock,
82}
83
84impl<'i> DeclarationParser<'i> for LonghandDeclarationParser {
85    type Declaration = ();
86    type Error = PropertyParseErrorKind<'i>;
87
88    fn parse_value<'t>(
89        &mut self,
90        name: CowRcStr<'i>,
91        parser: &mut Parser<'i, 't>,
92    ) -> Result<Self::Declaration, ParseError<'i, Self::Error>> {
93        if let Some(data) = property_data_by_name(&name) {
94            let previous_len = self.block.declarations.len();
95            let mut parsed;
96            if let Ok(keyword) = parser.r#try(CssWideKeyword::parse) {
97                parsed = PerPhase::default();
98                for &longhand in data.longhands {
99                    self.block
100                        .declarations
101                        .push(LonghandDeclaration::CssWide(longhand, keyword));
102                    if longhand.is_early() {
103                        parsed.early = true
104                    } else {
105                        parsed.late = true
106                    }
107                }
108            } else {
109                parsed = (data.parse)(parser, &mut self.block.declarations)?
110            }
111            let important = parser.r#try(cssparser::parse_important).is_ok();
112            let count = self.block.declarations.len() - previous_len;
113
114            if count > 0 {
115                self.block.important.extend(repeat(important).take(count));
116                let any = if important {
117                    &mut self.block.any_important
118                } else {
119                    &mut self.block.any_normal
120                };
121                any.early |= parsed.early;
122                any.late |= parsed.late;
123                Ok(())
124            } else {
125                Err(parser.new_custom_error(PropertyParseErrorKind::UnknownUnit(name)))
126            }
127        } else {
128            Err(parser.new_custom_error(PropertyParseErrorKind::UnknownProperty(name)))
129        }
130    }
131}
132
133impl<'i> AtRuleParser<'i> for LonghandDeclarationParser {
134    type PreludeNoBlock = ();
135    type PreludeBlock = ();
136    type AtRule = ();
137    type Error = PropertyParseErrorKind<'i>;
138}