mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Prehashed query result
This commit is contained in:
parent
af173acd59
commit
5764c65ec9
@ -79,6 +79,7 @@ fn retrieve(
|
||||
Ok(document
|
||||
.introspector
|
||||
.query(&selector.0)
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>())
|
||||
}
|
||||
|
@ -430,7 +430,7 @@ const OUTLINE_RULE: ShowFn<OutlineElem> = |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::<dyn Outlinable>() else {
|
||||
bail!(span, "cannot outline {}", elem.func().name());
|
||||
};
|
||||
|
@ -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());
|
||||
|
@ -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<Content> {
|
||||
pub fn query(&self, selector: &Selector) -> Prehashed<EcoVec<Content>> {
|
||||
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::<BTreeSet<usize>>()
|
||||
.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<K, V> Default for MultiMap<K, V> {
|
||||
|
||||
/// Caches queries.
|
||||
#[derive(Default)]
|
||||
struct QueryCache(RwLock<HashMap<u128, EcoVec<Content>>>);
|
||||
struct QueryCache(RwLock<HashMap<u128, Prehashed<EcoVec<Content>>>>);
|
||||
|
||||
impl QueryCache {
|
||||
fn get(&self, hash: u128) -> Option<EcoVec<Content>> {
|
||||
fn get(&self, hash: u128) -> Option<Prehashed<EcoVec<Content>>> {
|
||||
self.0.read().unwrap().get(&hash).cloned()
|
||||
}
|
||||
|
||||
fn insert(&self, hash: u128, output: EcoVec<Content>) {
|
||||
fn insert(&self, hash: u128, output: Prehashed<EcoVec<Content>>) {
|
||||
self.0.write().unwrap().insert(hash, output);
|
||||
}
|
||||
}
|
||||
|
@ -149,5 +149,5 @@ pub fn query(
|
||||
) -> HintedStrResult<Array> {
|
||||
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())
|
||||
}
|
||||
|
@ -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::<StateUpdateElem>().unwrap();
|
||||
match &elem.update {
|
||||
StateUpdate::Set(value) => state = value.clone(),
|
||||
|
@ -563,7 +563,7 @@ impl<'a> Generator<'a> {
|
||||
introspector: Tracked<Introspector>,
|
||||
) -> StrResult<Self> {
|
||||
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,
|
||||
|
@ -656,7 +656,7 @@ fn query_prefix_widths(
|
||||
) -> SmallVec<[Option<Abs>; 4]> {
|
||||
let mut widths = SmallVec::<[Option<Abs>; 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::<PrefixInfo>().unwrap();
|
||||
let level = info.level.get();
|
||||
if widths.len() < level {
|
||||
|
@ -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::<EmbedElem>().unwrap();
|
||||
let span = embed.span();
|
||||
let derived_path = &embed.path.derived;
|
||||
|
Loading…
x
Reference in New Issue
Block a user