Skip to main content

ass_core/analysis/styles/validation/
inheritance.rs

1//! Style inheritance tracking and analysis.
2//!
3//! Provides [`StyleInheritance`], a zero-copy tracker for the parent/child
4//! relationships of a style and for detecting circular inheritance.
5
6use alloc::vec::Vec;
7
8/// Style inheritance tracking and analysis
9#[derive(Debug, Clone)]
10pub struct StyleInheritance<'a> {
11    /// Style name (zero-copy reference)
12    pub name: &'a str,
13    /// Parent styles in inheritance chain
14    pub parents: Vec<&'a str>,
15    /// Child styles that inherit from this style
16    pub children: Vec<&'a str>,
17    /// Inheritance depth (0 = root style, no parents)
18    pub depth: usize,
19    /// Whether circular inheritance was detected
20    pub has_circular_inheritance: bool,
21}
22
23impl<'a> StyleInheritance<'a> {
24    /// Create new inheritance tracker for style
25    #[must_use]
26    pub const fn new(name: &'a str) -> Self {
27        Self {
28            name,
29            parents: Vec::new(),
30            children: Vec::new(),
31            depth: 0,
32            has_circular_inheritance: false,
33        }
34    }
35
36    /// Add parent style to inheritance chain
37    pub fn add_parent(&mut self, parent: &'a str) {
38        if !self.parents.contains(&parent) {
39            self.parents.push(parent);
40        }
41    }
42
43    /// Set parent style (for single inheritance)
44    pub fn set_parent(&mut self, parent: &'a str) {
45        self.parents.clear();
46        self.parents.push(parent);
47        self.depth = 1; // Will be adjusted later based on parent's depth
48    }
49
50    /// Add child style that inherits from this one
51    pub fn add_child(&mut self, child: &'a str) {
52        if !self.children.contains(&child) {
53            self.children.push(child);
54        }
55    }
56
57    /// Check if style has inheritance relationships
58    #[must_use]
59    pub fn has_inheritance(&self) -> bool {
60        !self.parents.is_empty() || !self.children.is_empty()
61    }
62
63    /// Check if style is root (no parents)
64    #[must_use]
65    pub fn is_root(&self) -> bool {
66        self.parents.is_empty()
67    }
68
69    /// Check if style is leaf (no children)
70    #[must_use]
71    pub fn is_leaf(&self) -> bool {
72        self.children.is_empty()
73    }
74}