use std::iter::FusedIterator;
use layout_api::{DangerousStyleNode, LayoutElement, LayoutNode};
use style::dom::{DomChildren, TElement, TShadowRoot};
use crate::layout_dom::{ServoDangerousStyleElement, ServoDangerousStyleNode, ServoLayoutNode};
pub struct ReverseChildrenIterator<'dom> {
current: Option<ServoLayoutNode<'dom>>,
}
impl<'dom> Iterator for ReverseChildrenIterator<'dom> {
type Item = ServoLayoutNode<'dom>;
#[expect(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
let node = self.current;
self.current = node.and_then(|node| unsafe { node.dangerous_previous_sibling() });
node
}
}
pub enum ServoLayoutNodeChildrenIterator<'dom> {
Node(Option<ServoLayoutNode<'dom>>),
Slottables(<Vec<ServoDangerousStyleNode<'dom>> as IntoIterator>::IntoIter),
}
impl<'dom> ServoLayoutNodeChildrenIterator<'dom> {
#[expect(unsafe_code)]
pub(super) fn new_for_flat_tree(parent: ServoLayoutNode<'dom>) -> Self {
if let Some(element) = parent.as_element() {
if let Some(shadow) = element.shadow_root() {
return Self::new_for_flat_tree(shadow.as_node().layout_node());
};
let element = unsafe { element.dangerous_style_element() };
let slotted_nodes = element.slotted_nodes();
if !slotted_nodes.is_empty() {
#[expect(clippy::unnecessary_to_owned)] return Self::Slottables(slotted_nodes.to_owned().into_iter());
}
}
Self::Node(unsafe { parent.dangerous_first_child() })
}
#[expect(unsafe_code)]
pub(super) fn new_for_dom_tree(parent: ServoLayoutNode<'dom>) -> Self {
Self::Node(unsafe { parent.dangerous_first_child() })
}
}
impl<'dom> Iterator for ServoLayoutNodeChildrenIterator<'dom> {
type Item = ServoLayoutNode<'dom>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Node(node) => {
#[expect(unsafe_code)]
let next_sibling = unsafe { (*node)?.dangerous_next_sibling() };
std::mem::replace(node, next_sibling)
},
Self::Slottables(slots) => slots.next().map(|node| node.layout_node()),
}
}
}
impl FusedIterator for ServoLayoutNodeChildrenIterator<'_> {}
pub enum DOMDescendantIterator<'dom> {
Children(DomChildren<ServoDangerousStyleNode<'dom>>),
Slottables {
slot: ServoDangerousStyleElement<'dom>,
index: usize,
},
}
impl<'dom> Iterator for DOMDescendantIterator<'dom> {
type Item = ServoDangerousStyleNode<'dom>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Children(children) => children.next(),
Self::Slottables { slot, index } => {
let slottables = slot.slotted_nodes();
let slot = slottables.get(*index)?;
*index += 1;
Some(*slot)
},
}
}
}