use std::cmp::Ordering;
use std::iter::Iterator;
use dom_struct::dom_struct;
use servo_atoms::Atom;
use style::custom_properties;
use super::bindings::trace::HashMapTracedValues;
use crate::dom::bindings::codegen::Bindings::StylePropertyMapReadOnlyBinding::StylePropertyMapReadOnlyMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::cssstylevalue::CSSStyleValue;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
#[dom_struct]
pub struct StylePropertyMapReadOnly {
reflector: Reflector,
entries: HashMapTracedValues<Atom, Dom<CSSStyleValue>>,
}
impl StylePropertyMapReadOnly {
fn new_inherited<Entries>(entries: Entries) -> StylePropertyMapReadOnly
where
Entries: IntoIterator<Item = (Atom, Dom<CSSStyleValue>)>,
{
StylePropertyMapReadOnly {
reflector: Reflector::new(),
entries: HashMapTracedValues(entries.into_iter().collect()),
}
}
pub fn from_iter<Entries>(
global: &GlobalScope,
entries: Entries,
) -> DomRoot<StylePropertyMapReadOnly>
where
Entries: IntoIterator<Item = (Atom, String)>,
{
let mut keys = Vec::new();
rooted_vec!(let mut values);
let iter = entries.into_iter();
let (lo, _) = iter.size_hint();
keys.reserve(lo);
values.reserve(lo);
for (key, value) in iter {
let value = CSSStyleValue::new(global, value);
keys.push(key);
values.push(Dom::from_ref(&*value));
}
let iter = keys.drain(..).zip(values.iter().cloned());
reflect_dom_object(
Box::new(StylePropertyMapReadOnly::new_inherited(iter)),
global,
CanGc::note(),
)
}
}
impl StylePropertyMapReadOnlyMethods<crate::DomTypeHolder> for StylePropertyMapReadOnly {
fn Get(&self, property: DOMString) -> Option<DomRoot<CSSStyleValue>> {
self.entries
.get(&Atom::from(property))
.map(|value| DomRoot::from_ref(&**value))
}
fn Has(&self, property: DOMString) -> bool {
self.entries.contains_key(&Atom::from(property))
}
fn GetProperties(&self) -> Vec<DOMString> {
let mut result: Vec<DOMString> = self
.entries
.0
.keys()
.map(|key| DOMString::from(&**key))
.collect();
result.sort_by(|key1, key2| {
if let Ok(key1) = custom_properties::parse_name(key1) {
if let Ok(key2) = custom_properties::parse_name(key2) {
key1.cmp(key2)
} else {
Ordering::Greater
}
} else if custom_properties::parse_name(key2).is_ok() {
Ordering::Less
} else {
key1.cmp(key2)
}
});
result
}
}