Simplify stable id handling

This commit is contained in:
Laurenz 2023-03-15 10:09:17 +01:00
parent 89f44f220d
commit 8567811808
10 changed files with 39 additions and 43 deletions

View File

@ -49,7 +49,7 @@ impl BibliographyNode {
/// Find the document's bibliography. /// Find the document's bibliography.
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> { pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> {
let mut iter = introspector.locate(Selector::node::<Self>()).into_iter(); let mut iter = introspector.locate(Selector::node::<Self>()).into_iter();
let Some((_, node)) = iter.next() else { let Some(node) = iter.next() else {
return Err("the document does not contain a bibliography".into()); return Err("the document does not contain a bibliography".into());
}; };
@ -65,7 +65,7 @@ impl BibliographyNode {
vt.introspector vt.introspector
.locate(Selector::node::<Self>()) .locate(Selector::node::<Self>())
.into_iter() .into_iter()
.flat_map(|(_, node)| load(vt.world(), &node.to::<Self>().unwrap().path())) .flat_map(|node| load(vt.world(), &node.to::<Self>().unwrap().path()))
.flatten() .flatten()
.any(|entry| entry.key() == key) .any(|entry| entry.key() == key)
} }
@ -280,9 +280,9 @@ impl Works {
let style = bibliography.style(StyleChain::default()); let style = bibliography.style(StyleChain::default());
let citations = vt let citations = vt
.locate_node::<CiteNode>() .locate_node::<CiteNode>()
.map(|(id, node)| { .map(|node| {
( (
id, node.0.stable_id().unwrap(),
node.key(), node.key(),
node.supplement(StyleChain::default()), node.supplement(StyleChain::default()),
node.style(StyleChain::default()) node.style(StyleChain::default())

View File

@ -58,7 +58,7 @@ impl FigureNode {
impl Synthesize for FigureNode { impl Synthesize for FigureNode {
fn synthesize(&mut self, vt: &Vt, styles: StyleChain) { fn synthesize(&mut self, vt: &Vt, styles: StyleChain) {
let my_id = self.0.stable_id().unwrap(); let my_id = self.0.stable_id();
let element = self.element(); let element = self.element();
let mut number = None; let mut number = None;
@ -67,8 +67,8 @@ impl Synthesize for FigureNode {
number = NonZeroUsize::new( number = NonZeroUsize::new(
1 + vt 1 + vt
.locate_node::<Self>() .locate_node::<Self>()
.take_while(|&(id, _)| id != my_id) .take_while(|figure| figure.0.stable_id() != my_id)
.filter(|(_, figure)| figure.element() == element) .filter(|figure| figure.element() == element)
.count(), .count(),
); );
} }

View File

@ -84,14 +84,15 @@ pub struct HeadingNode {
impl Synthesize for HeadingNode { impl Synthesize for HeadingNode {
fn synthesize(&mut self, vt: &Vt, styles: StyleChain) { fn synthesize(&mut self, vt: &Vt, styles: StyleChain) {
let my_id = self.0.stable_id().unwrap(); let my_id = self.0.stable_id();
let numbering = self.numbering(styles); let numbering = self.numbering(styles);
let mut counter = HeadingCounter::new(); let mut counter = HeadingCounter::new();
if numbering.is_some() { if numbering.is_some() {
// Advance past existing headings. // Advance past existing headings.
for (_, heading) in for heading in vt
vt.locate_node::<Self>().take_while(|&(id, _)| id != my_id) .locate_node::<Self>()
.take_while(|figure| figure.0.stable_id() != my_id)
{ {
if heading.numbering(StyleChain::default()).is_some() { if heading.numbering(StyleChain::default()).is_some() {
counter.advance(heading); counter.advance(heading);

View File

@ -77,8 +77,8 @@ impl Synthesize for OutlineNode {
fn synthesize(&mut self, vt: &Vt, _: StyleChain) { fn synthesize(&mut self, vt: &Vt, _: StyleChain) {
let headings = vt let headings = vt
.locate_node::<HeadingNode>() .locate_node::<HeadingNode>()
.map(|(_, node)| node.clone())
.filter(|node| node.outlined(StyleChain::default())) .filter(|node| node.outlined(StyleChain::default()))
.cloned()
.collect(); .collect();
self.push_headings(headings); self.push_headings(headings);

View File

@ -68,10 +68,7 @@ impl Show for RefNode {
let target = self.target(); let target = self.target();
let supplement = self.supplement(styles); let supplement = self.supplement(styles);
let matches: Vec<_> = vt let matches: Vec<_> = vt.locate(Selector::Label(self.target())).collect();
.locate(Selector::Label(self.target()))
.map(|(_, node)| node.clone())
.collect();
if !vt.locatable() || BibliographyNode::has(vt, &target.0) { if !vt.locatable() || BibliographyNode::has(vt, &target.0) {
if !matches.is_empty() { if !matches.is_empty() {
@ -87,7 +84,7 @@ impl Show for RefNode {
.spanned(self.span())); .spanned(self.span()));
} }
let [target] = matches.as_slice() else { let &[target] = matches.as_slice() else {
if vt.locatable() { if vt.locatable() {
bail!(self.span(), if matches.is_empty() { bail!(self.span(), if matches.is_empty() {
"label does not exist in the document" "label does not exist in the document"

View File

@ -14,7 +14,7 @@ use crate::geom::{
Numeric, Paint, Point, Rel, RgbaColor, Shape, Sides, Size, Stroke, Transform, Numeric, Paint, Point, Rel, RgbaColor, Shape, Sides, Size, Stroke, Transform,
}; };
use crate::image::Image; use crate::image::Image;
use crate::model::{node, Content, Fold, StableId, StyleChain}; use crate::model::{node, Content, Fold, StyleChain};
use crate::syntax::Span; use crate::syntax::Span;
/// A finished document with metadata and page frames. /// A finished document with metadata and page frames.
@ -597,7 +597,7 @@ pub enum Meta {
Link(Destination), Link(Destination),
/// An identifiable piece of content that produces something within the /// An identifiable piece of content that produces something within the
/// area this metadata is attached to. /// area this metadata is attached to.
Node(StableId, Content), Node(Content),
/// Indicates that the content is hidden. /// Indicates that the content is hidden.
Hidden, Hidden,
} }

View File

@ -288,7 +288,7 @@ fn write_frame(ctx: &mut PageContext, frame: &Frame) {
Element::Image(image, size) => write_image(ctx, x, y, image, *size), Element::Image(image, size) => write_image(ctx, x, y, image, *size),
Element::Meta(meta, size) => match meta { Element::Meta(meta, size) => match meta {
Meta::Link(dest) => write_link(ctx, pos, dest, *size), Meta::Link(dest) => write_link(ctx, pos, dest, *size),
Meta::Node(_, _) => {} Meta::Node(_) => {}
Meta::Hidden => {} Meta::Hidden => {}
}, },
} }

View File

@ -60,7 +60,7 @@ fn render_frame(
} }
Element::Meta(meta, _) => match meta { Element::Meta(meta, _) => match meta {
Meta::Link(_) => {} Meta::Link(_) => {}
Meta::Node(_, _) => {} Meta::Node(_) => {}
Meta::Hidden => {} Meta::Hidden => {}
}, },
} }

View File

@ -46,8 +46,8 @@ pub fn realize(
node.mark_prepared(); node.mark_prepared();
if let Some(id) = node.stable_id() { if node.stable_id().is_some() {
let meta = Meta::Node(id, node.clone()); let meta = Meta::Node(node.clone());
return Ok(Some(node.styled(MetaNode::set_data(vec![meta])))); return Ok(Some(node.styled(MetaNode::set_data(vec![meta]))));
} }

View File

@ -40,6 +40,8 @@ pub fn typeset(world: Tracked<dyn World>, content: &Content) -> SourceResult<Doc
} }
} }
log::debug!("Took {iter} iterations");
Ok(document) Ok(document)
} }
@ -80,17 +82,14 @@ impl<'a> Vt<'a> {
} }
/// Locate all metadata matches for the given selector. /// Locate all metadata matches for the given selector.
pub fn locate( pub fn locate(&self, selector: Selector) -> impl Iterator<Item = &Content> {
&self,
selector: Selector,
) -> impl Iterator<Item = (StableId, &Content)> {
self.introspector.locate(selector).into_iter() self.introspector.locate(selector).into_iter()
} }
/// Locate all metadata matches for the given node. /// Locate all metadata matches for the given node.
pub fn locate_node<T: Node>(&self) -> impl Iterator<Item = (StableId, &T)> { pub fn locate_node<T: Node>(&self) -> impl Iterator<Item = &T> {
self.locate(Selector::node::<T>()) self.locate(Selector::node::<T>())
.map(|(id, content)| (id, content.to::<T>().unwrap())) .map(|content| content.to::<T>().unwrap())
} }
} }
@ -102,7 +101,6 @@ pub struct StableId(u128, u64);
/// Provides stable identities to nodes. /// Provides stable identities to nodes.
#[derive(Clone)] #[derive(Clone)]
#[doc(hidden)]
pub struct StabilityProvider(HashMap<u128, u64>); pub struct StabilityProvider(HashMap<u128, u64>);
impl StabilityProvider { impl StabilityProvider {
@ -126,7 +124,7 @@ impl StabilityProvider {
/// Provides access to information about the document. /// Provides access to information about the document.
pub struct Introspector { pub struct Introspector {
init: bool, init: bool,
nodes: Vec<(StableId, Content)>, nodes: Vec<Content>,
queries: RefCell<Vec<(Selector, u128)>>, queries: RefCell<Vec<(Selector, u128)>>,
} }
@ -169,26 +167,30 @@ impl Introspector {
/// Iterate over all nodes. /// Iterate over all nodes.
pub fn iter(&self) -> impl Iterator<Item = &Content> { pub fn iter(&self) -> impl Iterator<Item = &Content> {
self.nodes.iter().map(|(_, node)| node) self.nodes.iter()
} }
/// Extract metadata from a frame. /// Extract metadata from a frame.
fn extract(&mut self, frame: &Frame, page: NonZeroUsize, ts: Transform) { fn extract(&mut self, frame: &Frame, page: NonZeroUsize, ts: Transform) {
for (pos, element) in frame.elements() { for (pos, element) in frame.elements() {
match *element { match element {
Element::Group(ref group) => { Element::Group(group) => {
let ts = ts let ts = ts
.pre_concat(Transform::translate(pos.x, pos.y)) .pre_concat(Transform::translate(pos.x, pos.y))
.pre_concat(group.transform); .pre_concat(group.transform);
self.extract(&group.frame, page, ts); self.extract(&group.frame, page, ts);
} }
Element::Meta(Meta::Node(id, ref content), _) => { Element::Meta(Meta::Node(content), _) => {
if !self.nodes.iter().any(|&(prev, _)| prev == id) { if !self
.nodes
.iter()
.any(|prev| prev.stable_id() == content.stable_id())
{
let pos = pos.transform(ts); let pos = pos.transform(ts);
let mut node = content.clone(); let mut node = content.clone();
let loc = Location { page, pos }; let loc = Location { page, pos };
node.push_field("location", loc); node.push_field("location", loc);
self.nodes.push((id, node)); self.nodes.push(node);
} }
} }
_ => {} _ => {}
@ -205,7 +207,7 @@ impl Introspector {
} }
/// Locate all metadata matches for the given selector. /// Locate all metadata matches for the given selector.
pub fn locate(&self, selector: Selector) -> Vec<(StableId, &Content)> { pub fn locate(&self, selector: Selector) -> Vec<&Content> {
let nodes = self.locate_impl(&selector); let nodes = self.locate_impl(&selector);
let mut queries = self.queries.borrow_mut(); let mut queries = self.queries.borrow_mut();
if !queries.iter().any(|(prev, _)| prev == &selector) { if !queries.iter().any(|(prev, _)| prev == &selector) {
@ -216,11 +218,7 @@ impl Introspector {
} }
impl Introspector { impl Introspector {
fn locate_impl(&self, selector: &Selector) -> Vec<(StableId, &Content)> { fn locate_impl(&self, selector: &Selector) -> Vec<&Content> {
self.nodes self.nodes.iter().filter(|target| selector.matches(target)).collect()
.iter()
.map(|(id, node)| (*id, node))
.filter(|(_, target)| selector.matches(target))
.collect()
} }
} }