diff --git a/crates/typst-cli/src/query.rs b/crates/typst-cli/src/query.rs index b1a446203..0a315aed6 100644 --- a/crates/typst-cli/src/query.rs +++ b/crates/typst-cli/src/query.rs @@ -79,6 +79,7 @@ fn retrieve( Ok(document .introspector .query(&selector.0) + .into_inner() .into_iter() .collect::>()) } diff --git a/crates/typst-layout/src/rules.rs b/crates/typst-layout/src/rules.rs index f21cd17ab..825529b33 100644 --- a/crates/typst-layout/src/rules.rs +++ b/crates/typst-layout/src/rules.rs @@ -430,7 +430,7 @@ const OUTLINE_RULE: ShowFn = |elem, engine, styles| { let depth = elem.depth.get(styles).unwrap_or(NonZeroUsize::MAX); // Build the outline entries. - for elem in elems { + for elem in elems.into_inner() { let Some(outlinable) = elem.with::() else { bail!(span, "cannot outline {}", elem.func().name()); }; diff --git a/crates/typst-library/src/introspection/counter.rs b/crates/typst-library/src/introspection/counter.rs index b3c52de4e..db62902ef 100644 --- a/crates/typst-library/src/introspection/counter.rs +++ b/crates/typst-library/src/introspection/counter.rs @@ -312,7 +312,7 @@ impl Counter { let mut page = NonZeroUsize::ONE; let mut stops = eco_vec![(state.clone(), page)]; - for elem in introspector.query(&self.selector()) { + for elem in introspector.query(&self.selector()).into_inner() { if self.is_page() { let prev = page; page = introspector.page(elem.location().unwrap()); diff --git a/crates/typst-library/src/introspection/introspector.rs b/crates/typst-library/src/introspection/introspector.rs index d40347323..7dd9971f9 100644 --- a/crates/typst-library/src/introspection/introspector.rs +++ b/crates/typst-library/src/introspection/introspector.rs @@ -4,6 +4,7 @@ use std::hash::Hash; use std::num::NonZeroUsize; use std::sync::RwLock; +use comemo::Prehashed; use ecow::{EcoString, EcoVec}; use smallvec::SmallVec; use typst_utils::NonZeroExt; @@ -108,7 +109,7 @@ impl Introspector { #[comemo::track] impl Introspector { /// Query for all matching elements. - pub fn query(&self, selector: &Selector) -> EcoVec { + pub fn query(&self, selector: &Selector) -> Prehashed> { let hash = typst_utils::hash128(selector); if let Some(output) = self.queries.get(hash) { return output; @@ -131,7 +132,7 @@ impl Introspector { .collect(), Selector::Or(selectors) => selectors .iter() - .flat_map(|sel| self.query(sel)) + .flat_map(|sel| self.query(sel).into_inner()) .map(|elem| self.elem_index(&elem)) .collect::>() .into_iter() @@ -139,7 +140,7 @@ impl Introspector { .collect(), Selector::And(selectors) => { let mut results: Vec<_> = - selectors.iter().map(|sel| self.query(sel)).collect(); + selectors.iter().map(|sel| self.query(sel).into_inner()).collect(); // Extract the smallest result list and then keep only those // elements in the smallest list that are also in all other @@ -161,7 +162,7 @@ impl Introspector { .collect() } Selector::Before { selector, end, inclusive } => { - let mut list = self.query(selector); + let mut list = self.query(selector).into_inner(); if let Some(end) = self.query_first(end) { // Determine which elements are before `end`. let split = match self.binary_search(&list, &end) { @@ -175,7 +176,7 @@ impl Introspector { list } Selector::After { selector, start, inclusive } => { - let mut list = self.query(selector); + let mut list = self.query(selector).into_inner(); if let Some(start) = self.query_first(start) { // Determine which elements are after `start`. let split = match self.binary_search(&list, &start) { @@ -192,6 +193,7 @@ impl Introspector { Selector::Can(_) | Selector::Regex(_) => EcoVec::new(), }; + let output = Prehashed::new(output); self.queries.insert(hash, output.clone()); output } @@ -223,6 +225,7 @@ impl Introspector { bail!("selector matches multiple elements",); } elems + .into_inner() .into_iter() .next() .ok_or_else(|| "selector does not match any element".into()) @@ -340,14 +343,14 @@ impl Default for MultiMap { /// Caches queries. #[derive(Default)] -struct QueryCache(RwLock>>); +struct QueryCache(RwLock>>>); impl QueryCache { - fn get(&self, hash: u128) -> Option> { + fn get(&self, hash: u128) -> Option>> { self.0.read().unwrap().get(&hash).cloned() } - fn insert(&self, hash: u128, output: EcoVec) { + fn insert(&self, hash: u128, output: Prehashed>) { self.0.write().unwrap().insert(hash, output); } } diff --git a/crates/typst-library/src/introspection/query.rs b/crates/typst-library/src/introspection/query.rs index b742ac010..618aec3b9 100644 --- a/crates/typst-library/src/introspection/query.rs +++ b/crates/typst-library/src/introspection/query.rs @@ -149,5 +149,5 @@ pub fn query( ) -> HintedStrResult { context.introspect()?; let vec = engine.introspector.query(&target.0); - Ok(vec.into_iter().map(Value::Content).collect()) + Ok(vec.into_inner().into_iter().map(Value::Content).collect()) } diff --git a/crates/typst-library/src/introspection/state.rs b/crates/typst-library/src/introspection/state.rs index 2d15a5de0..67d0bc3f0 100644 --- a/crates/typst-library/src/introspection/state.rs +++ b/crates/typst-library/src/introspection/state.rs @@ -242,7 +242,7 @@ impl State { let mut state = self.init.clone(); let mut stops = eco_vec![state.clone()]; - for elem in introspector.query(&self.selector()) { + for elem in introspector.query(&self.selector()).into_inner() { let elem = elem.to_packed::().unwrap(); match &elem.update { StateUpdate::Set(value) => state = value.clone(), diff --git a/crates/typst-library/src/model/bibliography.rs b/crates/typst-library/src/model/bibliography.rs index 188af4da1..d2e015684 100644 --- a/crates/typst-library/src/model/bibliography.rs +++ b/crates/typst-library/src/model/bibliography.rs @@ -563,7 +563,7 @@ impl<'a> Generator<'a> { introspector: Tracked, ) -> StrResult { let bibliography = BibliographyElem::find(introspector)?; - let groups = introspector.query(&CiteGroup::ELEM.select()); + let groups = introspector.query(&CiteGroup::ELEM.select()).into_inner(); let infos = Vec::with_capacity(groups.len()); Ok(Self { routines, diff --git a/crates/typst-library/src/model/outline.rs b/crates/typst-library/src/model/outline.rs index 4bda02ba3..35ad9714f 100644 --- a/crates/typst-library/src/model/outline.rs +++ b/crates/typst-library/src/model/outline.rs @@ -656,7 +656,7 @@ fn query_prefix_widths( ) -> SmallVec<[Option; 4]> { let mut widths = SmallVec::<[Option; 4]>::new(); let elems = introspector.query(&select_where!(PrefixInfo, key => outline_loc)); - for elem in &elems { + for elem in &elems.into_inner() { let info = elem.to_packed::().unwrap(); let level = info.level.get(); if widths.len() < level { diff --git a/crates/typst-pdf/src/embed.rs b/crates/typst-pdf/src/embed.rs index c62178cf2..19dcf2026 100644 --- a/crates/typst-pdf/src/embed.rs +++ b/crates/typst-pdf/src/embed.rs @@ -13,7 +13,7 @@ pub(crate) fn embed_files( ) -> SourceResult<()> { let elements = typst_doc.introspector.query(&EmbedElem::ELEM.select()); - for elem in &elements { + for elem in &elements.into_inner() { let embed = elem.to_packed::().unwrap(); let span = embed.span(); let derived_path = &embed.path.derived;