From ebfdb1dafa430786db10dad2ef7d5467c1bdbed1 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sun, 2 Jul 2023 19:59:52 +0200 Subject: Move everything into `crates/` directory --- src/model/content.rs | 614 --------------------------------------------------- 1 file changed, 614 deletions(-) delete mode 100644 src/model/content.rs (limited to 'src/model/content.rs') diff --git a/src/model/content.rs b/src/model/content.rs deleted file mode 100644 index 015f8b76..00000000 --- a/src/model/content.rs +++ /dev/null @@ -1,614 +0,0 @@ -use std::any::TypeId; -use std::fmt::{self, Debug, Formatter, Write}; -use std::iter::Sum; -use std::ops::{Add, AddAssign}; - -use comemo::Prehashed; -use ecow::{eco_format, EcoString, EcoVec}; - -use super::{ - element, Behave, Behaviour, ElemFunc, Element, Fold, Guard, Label, Locatable, - Location, Recipe, Selector, Style, Styles, Synthesize, -}; -use crate::diag::{SourceResult, StrResult}; -use crate::doc::Meta; -use crate::eval::{Dict, FromValue, IntoValue, Str, Value, Vm}; -use crate::syntax::Span; -use crate::util::pretty_array_like; - -/// Composable representation of styled content. -#[derive(Clone, Hash)] -#[allow(clippy::derived_hash_with_manual_eq)] -pub struct Content { - func: ElemFunc, - attrs: EcoVec, -} - -/// Attributes that can be attached to content. -#[derive(Debug, Clone, PartialEq, Hash)] -enum Attr { - Span(Span), - Field(EcoString), - Value(Prehashed), - Child(Prehashed), - Styles(Styles), - Prepared, - Guard(Guard), - Location(Location), -} - -impl Content { - /// Create an empty element. - pub fn new(func: ElemFunc) -> Self { - Self { func, attrs: EcoVec::new() } - } - - /// Create empty content. - pub fn empty() -> Self { - Self::new(SequenceElem::func()) - } - - /// Create a new sequence element from multiples elements. - pub fn sequence(iter: impl IntoIterator) -> Self { - let mut iter = iter.into_iter(); - let Some(first) = iter.next() else { return Self::empty() }; - let Some(second) = iter.next() else { return first }; - let mut content = Content::empty(); - content.attrs.push(Attr::Child(Prehashed::new(first))); - content.attrs.push(Attr::Child(Prehashed::new(second))); - content - .attrs - .extend(iter.map(|child| Attr::Child(Prehashed::new(child)))); - content - } - - /// The element function of the contained content. - pub fn func(&self) -> ElemFunc { - self.func - } - - /// Whether the content is an empty sequence. - pub fn is_empty(&self) -> bool { - self.is::() && self.attrs.is_empty() - } - - /// Whether the contained element is of type `T`. - pub fn is(&self) -> bool { - self.func == T::func() - } - - /// Cast to `T` if the contained element is of type `T`. - pub fn to(&self) -> Option<&T> { - T::unpack(self) - } - - /// Access the children if this is a sequence. - pub fn to_sequence(&self) -> Option> { - if !self.is::() { - return None; - } - Some(self.attrs.iter().filter_map(Attr::child)) - } - - /// Access the child and styles. - pub fn to_styled(&self) -> Option<(&Content, &Styles)> { - if !self.is::() { - return None; - } - let child = self.attrs.iter().find_map(Attr::child)?; - let styles = self.attrs.iter().find_map(Attr::styles)?; - Some((child, styles)) - } - - /// Whether the contained element has the given capability. - pub fn can(&self) -> bool - where - C: ?Sized + 'static, - { - (self.func.0.vtable)(TypeId::of::()).is_some() - } - - /// Whether the contained element has the given capability. - /// Where the capability is given by a `TypeId`. - pub fn can_type_id(&self, type_id: TypeId) -> bool { - (self.func.0.vtable)(type_id).is_some() - } - - /// Cast to a trait object if the contained element has the given - /// capability. - pub fn with(&self) -> Option<&C> - where - C: ?Sized + 'static, - { - let vtable = (self.func.0.vtable)(TypeId::of::())?; - let data = self as *const Self as *const (); - Some(unsafe { &*crate::util::fat::from_raw_parts(data, vtable) }) - } - - /// Cast to a mutable trait object if the contained element has the given - /// capability. - pub fn with_mut(&mut self) -> Option<&mut C> - where - C: ?Sized + 'static, - { - let vtable = (self.func.0.vtable)(TypeId::of::())?; - let data = self as *mut Self as *mut (); - Some(unsafe { &mut *crate::util::fat::from_raw_parts_mut(data, vtable) }) - } - - /// The content's span. - pub fn span(&self) -> Span { - self.attrs.iter().find_map(Attr::span).unwrap_or(Span::detached()) - } - - /// Attach a span to the content if it doesn't already have one. - pub fn spanned(mut self, span: Span) -> Self { - if self.span().is_detached() { - self.attrs.push(Attr::Span(span)); - } - self - } - - /// Attach a field to the content. - pub fn with_field( - mut self, - name: impl Into, - value: impl IntoValue, - ) -> Self { - self.push_field(name, value); - self - } - - /// Attach a field to the content. - pub fn push_field(&mut self, name: impl Into, value: impl IntoValue) { - let name = name.into(); - if let Some(i) = self.attrs.iter().position(|attr| match attr { - Attr::Field(field) => *field == name, - _ => false, - }) { - self.attrs.make_mut()[i + 1] = - Attr::Value(Prehashed::new(value.into_value())); - } else { - self.attrs.push(Attr::Field(name)); - self.attrs.push(Attr::Value(Prehashed::new(value.into_value()))); - } - } - - /// Access a field on the content. - pub fn field(&self, name: &str) -> Option { - if let (Some(iter), "children") = (self.to_sequence(), name) { - Some(Value::Array(iter.cloned().map(Value::Content).collect())) - } else if let (Some((child, _)), "child") = (self.to_styled(), name) { - Some(Value::Content(child.clone())) - } else { - self.field_ref(name).cloned() - } - } - - /// Access a field on the content by reference. - /// - /// Does not include synthesized fields for sequence and styled elements. - pub fn field_ref(&self, name: &str) -> Option<&Value> { - self.fields_ref() - .find(|&(field, _)| field == name) - .map(|(_, value)| value) - } - - /// Iter over all fields on the content. - /// - /// Does not include synthesized fields for sequence and styled elements. - pub fn fields(&self) -> impl Iterator { - static CHILD: EcoString = EcoString::inline("child"); - static CHILDREN: EcoString = EcoString::inline("children"); - - let option = if let Some(iter) = self.to_sequence() { - Some((&CHILDREN, Value::Array(iter.cloned().map(Value::Content).collect()))) - } else if let Some((child, _)) = self.to_styled() { - Some((&CHILD, Value::Content(child.clone()))) - } else { - None - }; - - self.fields_ref() - .map(|(name, value)| (name, value.clone())) - .chain(option) - } - - /// Iter over all fields on the content. - /// - /// Does not include synthesized fields for sequence and styled elements. - pub fn fields_ref(&self) -> impl Iterator { - let mut iter = self.attrs.iter(); - std::iter::from_fn(move || { - let field = iter.find_map(Attr::field)?; - let value = iter.next()?.value()?; - Some((field, value)) - }) - } - - /// Try to access a field on the content as a specified type. - pub fn cast_field(&self, name: &str) -> Option { - match self.field(name) { - Some(value) => value.cast().ok(), - None => None, - } - } - - /// Expect a field on the content to exist as a specified type. - #[track_caller] - pub fn expect_field(&self, name: &str) -> T { - self.field(name).unwrap().cast().unwrap() - } - - /// Whether the content has the specified field. - pub fn has(&self, field: &str) -> bool { - self.field(field).is_some() - } - - /// Borrow the value of the given field. - pub fn at(&self, field: &str, default: Option) -> StrResult { - self.field(field) - .or(default) - .ok_or_else(|| missing_field_no_default(field)) - } - - /// Return the fields of the content as a dict. - pub fn dict(&self) -> Dict { - self.fields() - .map(|(key, value)| (key.to_owned().into(), value)) - .collect() - } - - /// The content's label. - pub fn label(&self) -> Option<&Label> { - match self.field_ref("label")? { - Value::Label(label) => Some(label), - _ => None, - } - } - - /// Attach a label to the content. - pub fn labelled(self, label: Label) -> Self { - self.with_field("label", label) - } - - /// Style this content with a style entry. - pub fn styled(mut self, style: impl Into