diff options
| -rw-r--r-- | Cargo.lock | 7 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/model/content.rs | 39 |
3 files changed, 35 insertions, 12 deletions
@@ -1053,6 +1053,12 @@ dependencies = [ ] [[package]] +name = "thin-vec" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b" + +[[package]] name = "thiserror" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1127,6 +1133,7 @@ dependencies = [ "subsetter", "svg2pdf", "syntect", + "thin-vec", "tiny-skia", "ttf-parser 0.17.1", "typst-macros", @@ -32,6 +32,7 @@ siphasher = "0.3" subsetter = "0.1" svg2pdf = "0.4" syntect = { version = "5", default-features = false, features = ["default-syntaxes", "regex-fancy"] } +thin-vec = "0.2" tiny-skia = "0.6.2" ttf-parser = "0.17" unicode-segmentation = "1" diff --git a/src/model/content.rs b/src/model/content.rs index a7161798..2f7e7671 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -7,6 +7,7 @@ use std::sync::Arc; use comemo::Tracked; use siphasher::sip128::{Hasher128, SipHasher}; +use thin_vec::ThinVec; use typst_macros::node; use super::{capability, Args, Guard, Key, Property, Recipe, Style, StyleMap, Value, Vm}; @@ -19,9 +20,15 @@ use crate::World; #[derive(Clone, Hash)] pub struct Content { obj: Arc<dyn Bounds>, - guards: Vec<Guard>, span: Option<Span>, - label: Option<Label>, + meta: ThinVec<Meta>, +} + +/// Metadata that can be attached to content. +#[derive(Debug, Clone, PartialEq, Hash)] +enum Meta { + Guard(Guard), + Label(Label), } impl Content { @@ -55,7 +62,14 @@ impl Content { /// Attach a label to the content. pub fn labelled(mut self, label: Label) -> Self { - self.label = Some(label); + for meta in &mut self.meta { + if let Meta::Label(prev) = meta { + *prev = label; + return self; + } + } + + self.meta.push(Meta::Label(label)); self } @@ -132,13 +146,16 @@ impl Content { /// The content's label. pub fn label(&self) -> Option<&Label> { - self.label.as_ref() + self.meta.iter().find_map(|meta| match meta { + Meta::Label(label) => Some(label), + _ => None, + }) } /// Access a field on this content. pub fn field(&self, name: &str) -> Option<Value> { if name == "label" { - return Some(match &self.label { + return Some(match self.label() { Some(label) => Value::Label(label.clone()), None => Value::None, }); @@ -184,7 +201,7 @@ impl Content { /// Disable a show rule recipe. #[doc(hidden)] pub fn guarded(mut self, id: Guard) -> Self { - self.guards.push(id); + self.meta.push(Meta::Guard(id)); self } @@ -195,19 +212,18 @@ impl Content { /// Whether no show rule was executed for this node so far. pub(super) fn is_pristine(&self) -> bool { - self.guards.is_empty() + !self.meta.iter().any(|meta| matches!(meta, Meta::Guard(_))) } /// Check whether a show rule recipe is disabled. pub(super) fn is_guarded(&self, id: Guard) -> bool { - self.guards.contains(&id) + self.meta.contains(&Meta::Guard(id)) } /// Copy the metadata from other content. pub(super) fn copy_meta(&mut self, from: &Content) { - self.guards = from.guards.clone(); self.span = from.span; - self.label = from.label.clone(); + self.meta = from.meta.clone(); } } @@ -354,9 +370,8 @@ pub trait Node: 'static + Capable { { Content { obj: Arc::new(self), - guards: vec![], span: None, - label: None, + meta: ThinVec::new(), } } |
