Skip to content

Commit 5bc73be

Browse files
authored
Optimization to Introspector::extract (typst#734)
1 parent 72d8785 commit 5bc73be

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ unicode-xid = "0.2"
4343
unscanny = "0.1"
4444
usvg = { version = "0.22", default-features = false }
4545
xmp-writer = "0.1"
46+
indexmap = "1.9.3"
4647

4748
[profile.dev]
4849
debug = 0

src/model/introspect.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::fmt::{self, Debug, Formatter};
22
use std::hash::Hash;
33
use std::num::NonZeroUsize;
44

5+
use indexmap::IndexMap;
6+
57
use super::{Content, Selector};
68
use crate::diag::StrResult;
79
use crate::doc::{Frame, FrameItem, Meta, Position};
@@ -83,7 +85,7 @@ impl StabilityProvider {
8385
/// Can be queried for elements and their positions.
8486
pub struct Introspector {
8587
pages: usize,
86-
elems: Vec<(Content, Position)>,
88+
elems: IndexMap<Option<Location>, (Content, Position)>,
8789
// Indexed by page number.
8890
page_numberings: Vec<Value>,
8991
}
@@ -93,7 +95,7 @@ impl Introspector {
9395
pub fn new(frames: &[Frame]) -> Self {
9496
let mut introspector = Self {
9597
pages: frames.len(),
96-
elems: vec![],
98+
elems: IndexMap::new(),
9799
page_numberings: vec![],
98100
};
99101
for (i, frame) in frames.iter().enumerate() {
@@ -105,7 +107,7 @@ impl Introspector {
105107

106108
/// Iterate over all elements.
107109
pub fn all(&self) -> impl Iterator<Item = &Content> {
108-
self.elems.iter().map(|(elem, _)| elem)
110+
self.elems.values().map(|(elem, _)| elem)
109111
}
110112

111113
/// Extract metadata from a frame.
@@ -119,13 +121,14 @@ impl Introspector {
119121
self.extract(&group.frame, page, ts);
120122
}
121123
FrameItem::Meta(Meta::Elem(content), _)
122-
if !self
123-
.elems
124-
.iter()
125-
.any(|(prev, _)| prev.location() == content.location()) =>
124+
if !self.elems.contains_key(&content.location()) =>
126125
{
127126
let pos = pos.transform(ts);
128-
self.elems.push((content.clone(), Position { page, point: pos }));
127+
let ret = self.elems.insert(
128+
content.location(),
129+
(content.clone(), Position { page, point: pos }),
130+
);
131+
assert!(ret.is_none(), "duplicate locations");
129132
}
130133
FrameItem::Meta(Meta::PageNumbering(numbering), _) => {
131134
self.page_numberings.push(numbering.clone());
@@ -202,8 +205,7 @@ impl Introspector {
202205
/// Find the position for the given location.
203206
pub fn position(&self, location: Location) -> Position {
204207
self.elems
205-
.iter()
206-
.find(|(elem, _)| elem.location() == Some(location))
208+
.get(&Some(location))
207209
.map(|(_, loc)| *loc)
208210
.unwrap_or(Position { page: NonZeroUsize::ONE, point: Point::zero() })
209211
}

0 commit comments

Comments
 (0)