use crate::element::ElementData;
use crate::error::Result;
use crate::event_provider::Subscription;
use crate::selector::{matches_simple, Combinator, Selector, SelectorSegment};
pub trait Provider: Send + Sync {
fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>>;
fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>>;
fn find_elements(
&self,
root: Option<&ElementData>,
selector: &Selector,
limit: Option<usize>,
max_depth: Option<u32>,
) -> Result<Vec<ElementData>> {
crate::selector::find_elements_in_tree(
|el| self.get_children(el),
root,
selector,
limit,
max_depth,
)
}
fn narrow_multi_segment(
&self,
mut candidates: Vec<ElementData>,
segments: &[SelectorSegment],
max_depth: u32,
limit: Option<usize>,
) -> Result<Vec<ElementData>> {
for segment in segments {
let mut next_candidates = Vec::new();
for candidate in &candidates {
match segment.combinator {
Combinator::Child => {
let children = self.get_children(Some(candidate))?;
for child in children {
if matches_simple(&child, &segment.simple) {
next_candidates.push(child);
}
}
}
Combinator::Descendant => {
let sub_selector = Selector {
segments: vec![SelectorSegment {
combinator: Combinator::Root,
simple: segment.simple.clone(),
}],
};
let mut sub_results = self.find_elements(
Some(candidate),
&sub_selector,
None,
Some(max_depth),
)?;
next_candidates.append(&mut sub_results);
}
Combinator::Root => unreachable!(),
}
}
let mut seen = std::collections::HashSet::new();
next_candidates.retain(|e| seen.insert(e.handle));
candidates = next_candidates;
}
if let Some(nth) = segments.last().and_then(|s| s.simple.nth) {
if nth <= candidates.len() {
candidates = vec![candidates.remove(nth - 1)];
} else {
candidates.clear();
}
}
if let Some(limit) = limit {
candidates.truncate(limit);
}
Ok(candidates)
}
fn press(&self, element: &ElementData) -> Result<()>;
fn focus(&self, element: &ElementData) -> Result<()>;
fn blur(&self, element: &ElementData) -> Result<()>;
fn toggle(&self, element: &ElementData) -> Result<()>;
fn select(&self, element: &ElementData) -> Result<()>;
fn expand(&self, element: &ElementData) -> Result<()>;
fn collapse(&self, element: &ElementData) -> Result<()>;
fn show_menu(&self, element: &ElementData) -> Result<()>;
fn increment(&self, element: &ElementData) -> Result<()>;
fn decrement(&self, element: &ElementData) -> Result<()>;
fn scroll_into_view(&self, element: &ElementData) -> Result<()>;
fn set_value(&self, element: &ElementData, value: &str) -> Result<()>;
fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()>;
fn type_text(&self, element: &ElementData, text: &str) -> Result<()>;
fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()>;
fn perform_action(&self, element: &ElementData, action: &str) -> Result<()>;
fn subscribe(&self, element: &ElementData) -> Result<Subscription>;
}
impl<T: Provider + ?Sized> Provider for &T {
fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>> {
(**self).get_children(element)
}
fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>> {
(**self).get_parent(element)
}
fn find_elements(
&self,
root: Option<&ElementData>,
selector: &Selector,
limit: Option<usize>,
max_depth: Option<u32>,
) -> Result<Vec<ElementData>> {
(**self).find_elements(root, selector, limit, max_depth)
}
fn narrow_multi_segment(
&self,
candidates: Vec<ElementData>,
segments: &[SelectorSegment],
max_depth: u32,
limit: Option<usize>,
) -> Result<Vec<ElementData>> {
(**self).narrow_multi_segment(candidates, segments, max_depth, limit)
}
fn press(&self, element: &ElementData) -> Result<()> {
(**self).press(element)
}
fn focus(&self, element: &ElementData) -> Result<()> {
(**self).focus(element)
}
fn blur(&self, element: &ElementData) -> Result<()> {
(**self).blur(element)
}
fn toggle(&self, element: &ElementData) -> Result<()> {
(**self).toggle(element)
}
fn select(&self, element: &ElementData) -> Result<()> {
(**self).select(element)
}
fn expand(&self, element: &ElementData) -> Result<()> {
(**self).expand(element)
}
fn collapse(&self, element: &ElementData) -> Result<()> {
(**self).collapse(element)
}
fn show_menu(&self, element: &ElementData) -> Result<()> {
(**self).show_menu(element)
}
fn increment(&self, element: &ElementData) -> Result<()> {
(**self).increment(element)
}
fn decrement(&self, element: &ElementData) -> Result<()> {
(**self).decrement(element)
}
fn scroll_into_view(&self, element: &ElementData) -> Result<()> {
(**self).scroll_into_view(element)
}
fn set_value(&self, element: &ElementData, value: &str) -> Result<()> {
(**self).set_value(element, value)
}
fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()> {
(**self).set_numeric_value(element, value)
}
fn type_text(&self, element: &ElementData, text: &str) -> Result<()> {
(**self).type_text(element, text)
}
fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()> {
(**self).set_text_selection(element, start, end)
}
fn perform_action(&self, element: &ElementData, action: &str) -> Result<()> {
(**self).perform_action(element, action)
}
fn subscribe(&self, element: &ElementData) -> Result<Subscription> {
(**self).subscribe(element)
}
}