summaryrefslogtreecommitdiff
path: root/src/model/show.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-04-24 15:42:56 +0200
committerLaurenz <laurmaedje@gmail.com>2022-04-24 15:47:42 +0200
commit8fbb11fc05b3313bf102c1f23693290661d00863 (patch)
treea198db77338f1cc1304fe50f55020b08e22bca60 /src/model/show.rs
parente4ee14e54fb87961096856c7ea105435b7cc3c45 (diff)
Extract `model` module
Diffstat (limited to 'src/model/show.rs')
-rw-r--r--src/model/show.rs112
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
+ }
+}