Skip to main content

scah/selection_engine/
multiplexer.rs

1use std::fmt::Debug;
2
3use super::executor::QueryExecutor;
4use crate::XHtmlElement;
5use crate::css::selector::Query;
6use crate::store::Store;
7
8pub(crate) struct DocumentPosition {
9    pub reader_position: usize,
10    pub text_content_position: usize,
11    pub element_depth: crate::selection_engine::DepthSize,
12}
13
14//type Runner<'query, E> = SmallVec<[QueryExecutor<'query, 'query, E>; 1]>;
15type Runner<'query> = Vec<QueryExecutor<'query, 'query>>;
16
17#[derive(Debug)]
18pub struct QueryMultiplexer<'query> {
19    runners: Runner<'query>,
20}
21
22impl<'html, 'query: 'html> QueryMultiplexer<'query> {
23    pub fn new(queries: &'query [Query<'query>]) -> Self {
24        Self {
25            #[allow(clippy::redundant_closure)]
26            runners: queries
27                .iter()
28                .map(|query| QueryExecutor::new(query))
29                .collect::<Runner<'query>>(),
30        }
31    }
32
33    pub(crate) fn next(
34        &mut self,
35        xhtml_element: &XHtmlElement<'html>,
36        position: &DocumentPosition,
37        store: &mut Store<'html, 'query>,
38    ) {
39        let len = store.elements.len();
40        for session in self.runners.iter_mut() {
41            session.next(xhtml_element, position, store);
42        }
43        if len == store.elements.len() {
44            // Element was not saved
45            // Thus delete from the tape
46            xhtml_element.remove_attributes(&mut store.attributes);
47        }
48    }
49
50    pub(crate) fn back(
51        &mut self,
52        xhtml_element: &'html str,
53        position: &DocumentPosition,
54        reader: &crate::utils::Reader<'html>,
55        store: &mut Store<'html, 'query>,
56    ) -> bool {
57        let mut remove_indices = vec![];
58        for (index, session) in self.runners.iter_mut().enumerate() {
59            let early_exit = session.early_exit();
60            let back = session.back(store, xhtml_element, position, reader);
61
62            if early_exit && back {
63                remove_indices.push(index);
64            }
65        }
66        for idx in remove_indices {
67            self.runners.remove(idx);
68        }
69
70        self.runners.is_empty()
71    }
72}