use std::sync::{Arc, Mutex};
use crate::cssrule::CSSRuleTrait;
#[derive(Clone)]
pub struct CSSRuleList {
rules: Vec<Arc<Mutex<dyn CSSRuleTrait>>>,
}
impl std::fmt::Debug for CSSRuleList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CSSRuleList")
.field("rules_count", &self.rules.len())
.finish()
}
}
impl CSSRuleList {
pub fn new() -> Self {
Self {
rules: Vec::new(),
}
}
pub fn from_rules(rules: Vec<Arc<Mutex<dyn CSSRuleTrait>>>) -> Self {
Self { rules }
}
pub fn length(&self) -> u32 {
self.rules.len() as u32
}
pub fn item(&self, index: u32) -> Option<Arc<Mutex<dyn CSSRuleTrait>>> {
if index < self.rules.len() as u32 {
Some(Arc::clone(&self.rules[index as usize]))
} else {
None
}
}
pub fn append_rule(&mut self, rule: Arc<Mutex<dyn CSSRuleTrait>>) {
self.rules.push(rule);
}
pub fn insert_rule(&mut self, rule: Arc<Mutex<dyn CSSRuleTrait>>, index: usize) -> bool {
if index > self.rules.len() {
return false;
}
self.rules.insert(index, rule);
true
}
pub fn remove_rule(&mut self, index: usize) -> bool {
if index < self.rules.len() {
self.rules.remove(index);
true
} else {
false
}
}
pub fn clear(&mut self) {
self.rules.clear();
}
pub fn iter(&self) -> impl Iterator<Item = &Arc<Mutex<dyn CSSRuleTrait>>> {
self.rules.iter()
}
pub fn get_all_css_texts(&self) -> Vec<String> {
self.rules
.iter()
.map(|r| r.lock().unwrap().get_css_text().to_string())
.collect()
}
}
impl Default for CSSRuleList {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cssrule::CSSStyleRule;
#[test]
fn test_new_list() {
let list = CSSRuleList::new();
assert_eq!(list.length(), 0);
}
#[test]
fn test_append_rule() {
let mut list = CSSRuleList::new();
let rule = Arc::new(Mutex::new(CSSStyleRule::new(".class")));
list.append_rule(rule);
assert_eq!(list.length(), 1);
}
#[test]
fn test_item() {
let mut list = CSSRuleList::new();
let rule = Arc::new(Mutex::new(CSSStyleRule::new(".class")));
list.append_rule(rule.clone());
let retrieved = list.item(0);
assert!(retrieved.is_some());
let not_found = list.item(1);
assert!(not_found.is_none());
}
#[test]
fn test_insert_rule() {
let mut list = CSSRuleList::new();
let rule1 = Arc::new(Mutex::new(CSSStyleRule::new(".class1")));
let rule2 = Arc::new(Mutex::new(CSSStyleRule::new(".class2")));
list.append_rule(rule1);
list.insert_rule(rule2, 0);
assert_eq!(list.length(), 2);
assert!(list.item(0).unwrap().lock().unwrap().get_css_text().contains(".class2"));
}
#[test]
fn test_remove_rule() {
let mut list = CSSRuleList::new();
let rule = Arc::new(Mutex::new(CSSStyleRule::new(".class")));
list.append_rule(rule);
assert!(list.remove_rule(0));
assert_eq!(list.length(), 0);
assert!(!list.remove_rule(0)); }
#[test]
fn test_clear() {
let mut list = CSSRuleList::new();
list.append_rule(Arc::new(Mutex::new(CSSStyleRule::new(".class1"))));
list.append_rule(Arc::new(Mutex::new(CSSStyleRule::new(".class2"))));
list.clear();
assert_eq!(list.length(), 0);
}
#[test]
fn test_get_all_css_texts() {
let mut list = CSSRuleList::new();
list.append_rule(Arc::new(Mutex::new(CSSStyleRule::new(".class1"))));
list.append_rule(Arc::new(Mutex::new(CSSStyleRule::new(".class2"))));
let texts = list.get_all_css_texts();
assert_eq!(texts.len(), 2);
assert!(texts[0].contains(".class1"));
assert!(texts[1].contains(".class2"));
}
}