diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-04-24 15:42:56 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-04-24 15:47:42 +0200 |
| commit | 8fbb11fc05b3313bf102c1f23693290661d00863 (patch) | |
| tree | a198db77338f1cc1304fe50f55020b08e22bca60 /src/model/show.rs | |
| parent | e4ee14e54fb87961096856c7ea105435b7cc3c45 (diff) | |
Extract `model` module
Diffstat (limited to 'src/model/show.rs')
| -rw-r--r-- | src/model/show.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/model/show.rs b/src/model/show.rs new file mode 100644 index 00000000..5f76ba19 --- /dev/null +++ b/src/model/show.rs @@ -0,0 +1,112 @@ +use std::any::{Any, TypeId}; +use std::fmt::{self, Debug, Formatter}; +use std::hash::Hash; +use std::sync::Arc; + +use super::{Content, StyleChain}; +use crate::diag::TypResult; +use crate::eval::Dict; +use crate::util::Prehashed; +use crate::Context; + +/// A node that can be realized given some styles. +pub trait Show: 'static { + /// Encode this node into a dictionary. + fn encode(&self) -> Dict; + + /// The base recipe for this node that is executed if there is no + /// user-defined show rule. + fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content>; + + /// Finalize this node given the realization of a base or user recipe. Use + /// this for effects that should work even in the face of a user-defined + /// show rule, for example: + /// - Application of general settable properties + /// - Attaching things like semantics to a heading + /// + /// Defaults to just the realized content. + #[allow(unused_variables)] + fn finalize( + &self, + ctx: &mut Context, + styles: StyleChain, + realized: Content, + ) -> TypResult<Content> { + Ok(realized) + } + + /// Convert to a packed show node. + fn pack(self) -> ShowNode + where + Self: Debug + Hash + Sized + Sync + Send + 'static, + { + ShowNode::new(self) + } +} + +/// A type-erased showable node with a precomputed hash. +#[derive(Clone, Hash)] +pub struct ShowNode(Arc<Prehashed<dyn Bounds>>); + +impl ShowNode { + /// Pack any showable node. + pub fn new<T>(node: T) -> Self + where + T: Show + Debug + Hash + Sync + Send + 'static, + { + Self(Arc::new(Prehashed::new(node))) + } + + /// The type id of this node. + pub fn id(&self) -> TypeId { + self.0.as_any().type_id() + } +} + +impl Show for ShowNode { + fn encode(&self) -> Dict { + self.0.encode() + } + + fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> { + self.0.realize(ctx, styles) + } + + fn finalize( + &self, + ctx: &mut Context, + styles: StyleChain, + realized: Content, + ) -> TypResult<Content> { + self.0.finalize(ctx, styles, realized) + } + + fn pack(self) -> ShowNode { + self + } +} + +impl Debug for ShowNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl PartialEq for ShowNode { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} + +trait Bounds: Show + Debug + Sync + Send + 'static { + fn as_any(&self) -> &dyn Any; +} + +impl<T> Bounds for T +where + T: Show + Debug + Hash + Sync + Send + 'static, +{ + fn as_any(&self) -> &dyn Any { + self + } +} |
