Optimization to Introspector::extract (#734)

This commit is contained in:
Daniel Csillag 2023-04-11 14:11:44 -03:00 committed by GitHub
parent 72d8785abe
commit 5bc73be90f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 12 deletions

5
Cargo.lock generated
View File

@ -731,9 +731,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.2" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown",
@ -1606,6 +1606,7 @@ dependencies = [
"flate2", "flate2",
"if_chain", "if_chain",
"image", "image",
"indexmap",
"log", "log",
"miniz_oxide 0.5.4", "miniz_oxide 0.5.4",
"once_cell", "once_cell",

View File

@ -43,6 +43,7 @@ unicode-xid = "0.2"
unscanny = "0.1" unscanny = "0.1"
usvg = { version = "0.22", default-features = false } usvg = { version = "0.22", default-features = false }
xmp-writer = "0.1" xmp-writer = "0.1"
indexmap = "1.9.3"
[profile.dev] [profile.dev]
debug = 0 debug = 0

View File

@ -2,6 +2,8 @@ use std::fmt::{self, Debug, Formatter};
use std::hash::Hash; use std::hash::Hash;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use indexmap::IndexMap;
use super::{Content, Selector}; use super::{Content, Selector};
use crate::diag::StrResult; use crate::diag::StrResult;
use crate::doc::{Frame, FrameItem, Meta, Position}; use crate::doc::{Frame, FrameItem, Meta, Position};
@ -83,7 +85,7 @@ impl StabilityProvider {
/// Can be queried for elements and their positions. /// Can be queried for elements and their positions.
pub struct Introspector { pub struct Introspector {
pages: usize, pages: usize,
elems: Vec<(Content, Position)>, elems: IndexMap<Option<Location>, (Content, Position)>,
// Indexed by page number. // Indexed by page number.
page_numberings: Vec<Value>, page_numberings: Vec<Value>,
} }
@ -93,7 +95,7 @@ impl Introspector {
pub fn new(frames: &[Frame]) -> Self { pub fn new(frames: &[Frame]) -> Self {
let mut introspector = Self { let mut introspector = Self {
pages: frames.len(), pages: frames.len(),
elems: vec![], elems: IndexMap::new(),
page_numberings: vec![], page_numberings: vec![],
}; };
for (i, frame) in frames.iter().enumerate() { for (i, frame) in frames.iter().enumerate() {
@ -105,7 +107,7 @@ impl Introspector {
/// Iterate over all elements. /// Iterate over all elements.
pub fn all(&self) -> impl Iterator<Item = &Content> { pub fn all(&self) -> impl Iterator<Item = &Content> {
self.elems.iter().map(|(elem, _)| elem) self.elems.values().map(|(elem, _)| elem)
} }
/// Extract metadata from a frame. /// Extract metadata from a frame.
@ -119,13 +121,14 @@ impl Introspector {
self.extract(&group.frame, page, ts); self.extract(&group.frame, page, ts);
} }
FrameItem::Meta(Meta::Elem(content), _) FrameItem::Meta(Meta::Elem(content), _)
if !self if !self.elems.contains_key(&content.location()) =>
.elems
.iter()
.any(|(prev, _)| prev.location() == content.location()) =>
{ {
let pos = pos.transform(ts); let pos = pos.transform(ts);
self.elems.push((content.clone(), Position { page, point: pos })); let ret = self.elems.insert(
content.location(),
(content.clone(), Position { page, point: pos }),
);
assert!(ret.is_none(), "duplicate locations");
} }
FrameItem::Meta(Meta::PageNumbering(numbering), _) => { FrameItem::Meta(Meta::PageNumbering(numbering), _) => {
self.page_numberings.push(numbering.clone()); self.page_numberings.push(numbering.clone());
@ -202,8 +205,7 @@ impl Introspector {
/// Find the position for the given location. /// Find the position for the given location.
pub fn position(&self, location: Location) -> Position { pub fn position(&self, location: Location) -> Position {
self.elems self.elems
.iter() .get(&Some(location))
.find(|(elem, _)| elem.location() == Some(location))
.map(|(_, loc)| *loc) .map(|(_, loc)| *loc)
.unwrap_or(Position { page: NonZeroUsize::ONE, point: Point::zero() }) .unwrap_or(Position { page: NonZeroUsize::ONE, point: Point::zero() })
} }