1use std::any::TypeId;
2use std::fmt::{self, Debug, Formatter};
3use std::hash::{Hash, Hasher};
4use std::iter::{self, Sum};
5use std::marker::PhantomData;
6use std::ops::{Add, AddAssign, Deref, DerefMut};
7use std::sync::Arc;
8
9use comemo::Tracked;
10use ecow::{eco_format, EcoString};
11use serde::{Serialize, Serializer};
12use typst_syntax::Span;
13use typst_utils::{fat, singleton, LazyHash, SmallBitSet};
14
15use crate::diag::{SourceResult, StrResult};
16use crate::engine::Engine;
17use crate::foundations::{
18 elem, func, scope, ty, Context, Dict, Element, Fields, IntoValue, Label,
19 NativeElement, Recipe, RecipeIndex, Repr, Selector, Str, Style, StyleChain, Styles,
20 Value,
21};
22use crate::introspection::Location;
23use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
24use crate::model::{Destination, EmphElem, LinkElem, StrongElem};
25use crate::text::UnderlineElem;
26
27#[ty(scope, cast)]
71#[derive(Clone, Hash)]
72#[allow(clippy::derived_hash_with_manual_eq)]
73pub struct Content {
74 inner: Arc<Inner<dyn Bounds>>,
76 span: Span,
78}
79
80#[derive(Hash)]
82struct Inner<T: ?Sized + 'static> {
83 label: Option<Label>,
85 location: Option<Location>,
87 lifecycle: SmallBitSet,
92 elem: LazyHash<T>,
94}
95
96impl Content {
97 pub fn new<T: NativeElement>(elem: T) -> Self {
99 Self {
100 inner: Arc::new(Inner {
101 label: None,
102 location: None,
103 lifecycle: SmallBitSet::new(),
104 elem: elem.into(),
105 }),
106 span: Span::detached(),
107 }
108 }
109
110 pub fn empty() -> Self {
112 singleton!(Content, SequenceElem::default().pack()).clone()
113 }
114
115 pub fn elem(&self) -> Element {
117 self.inner.elem.dyn_elem()
118 }
119
120 pub fn span(&self) -> Span {
122 self.span
123 }
124
125 pub fn spanned(mut self, span: Span) -> Self {
127 if self.span.is_detached() {
128 self.span = span;
129 }
130 self
131 }
132
133 pub fn label(&self) -> Option<Label> {
135 self.inner.label
136 }
137
138 pub fn labelled(mut self, label: Label) -> Self {
140 self.set_label(label);
141 self
142 }
143
144 pub fn set_label(&mut self, label: Label) {
146 self.make_mut().label = Some(label);
147 }
148
149 pub fn located(mut self, loc: Location) -> Self {
156 self.set_location(loc);
157 self
158 }
159
160 pub fn set_location(&mut self, location: Location) {
162 self.make_mut().location = Some(location);
163 }
164
165 pub fn is_guarded(&self, index: RecipeIndex) -> bool {
167 self.inner.lifecycle.contains(index.0)
168 }
169
170 pub fn guarded(mut self, index: RecipeIndex) -> Self {
172 self.make_mut().lifecycle.insert(index.0);
173 self
174 }
175
176 pub fn is_prepared(&self) -> bool {
178 self.inner.lifecycle.contains(0)
179 }
180
181 pub fn mark_prepared(&mut self) {
183 self.make_mut().lifecycle.insert(0);
184 }
185
186 pub fn get(
192 &self,
193 id: u8,
194 styles: Option<StyleChain>,
195 ) -> Result<Value, FieldAccessError> {
196 if id == 255 {
197 if let Some(label) = self.label() {
198 return Ok(label.into_value());
199 }
200 }
201 match styles {
202 Some(styles) => self.inner.elem.field_with_styles(id, styles),
203 None => self.inner.elem.field(id),
204 }
205 }
206
207 pub fn get_by_name(&self, name: &str) -> Result<Value, FieldAccessError> {
212 if name == "label" {
213 return self
214 .label()
215 .map(|label| label.into_value())
216 .ok_or(FieldAccessError::Unknown);
217 }
218 let id = self.elem().field_id(name).ok_or(FieldAccessError::Unknown)?;
219 self.get(id, None)
220 }
221
222 pub fn field(&self, id: u8) -> StrResult<Value> {
228 self.get(id, None)
229 .map_err(|e| e.message(self, self.elem().field_name(id).unwrap()))
230 }
231
232 pub fn field_by_name(&self, name: &str) -> StrResult<Value> {
238 self.get_by_name(name).map_err(|e| e.message(self, name))
239 }
240
241 pub fn materialize(&mut self, styles: StyleChain) {
243 self.make_mut().elem.materialize(styles);
244 }
245
246 pub fn sequence(iter: impl IntoIterator<Item = Self>) -> Self {
248 let vec: Vec<_> = iter.into_iter().collect();
249 if vec.is_empty() {
250 Self::empty()
251 } else if vec.len() == 1 {
252 vec.into_iter().next().unwrap()
253 } else {
254 SequenceElem::new(vec).into()
255 }
256 }
257
258 pub fn is<T: NativeElement>(&self) -> bool {
260 self.inner.elem.dyn_type_id() == TypeId::of::<T>()
261 }
262
263 pub fn to_packed<T: NativeElement>(&self) -> Option<&Packed<T>> {
265 Packed::from_ref(self)
266 }
267
268 pub fn to_packed_mut<T: NativeElement>(&mut self) -> Option<&mut Packed<T>> {
270 Packed::from_mut(self)
271 }
272
273 pub fn into_packed<T: NativeElement>(self) -> Result<Packed<T>, Self> {
275 Packed::from_owned(self)
276 }
277
278 pub fn unpack<T: NativeElement>(self) -> Result<T, Self> {
280 self.into_packed::<T>().map(Packed::unpack)
281 }
282
283 fn make_mut(&mut self) -> &mut Inner<dyn Bounds> {
286 let arc = &mut self.inner;
287 if Arc::strong_count(arc) > 1 || Arc::weak_count(arc) > 0 {
288 *self = arc.elem.dyn_clone(arc, self.span);
289 }
290 Arc::get_mut(&mut self.inner).unwrap()
291 }
292
293 pub fn can<C>(&self) -> bool
295 where
296 C: ?Sized + 'static,
297 {
298 self.elem().can::<C>()
299 }
300
301 pub fn with<C>(&self) -> Option<&C>
304 where
305 C: ?Sized + 'static,
306 {
307 let vtable = self.elem().vtable()(TypeId::of::<C>())?;
312 let data = self as *const Content as *const ();
313 Some(unsafe { &*fat::from_raw_parts(data, vtable.as_ptr()) })
314 }
315
316 pub fn with_mut<C>(&mut self) -> Option<&mut C>
319 where
320 C: ?Sized + 'static,
321 {
322 let vtable = self.elem().vtable()(TypeId::of::<C>())?;
332 let data = self as *mut Content as *mut ();
333 Some(unsafe { &mut *fat::from_raw_parts_mut(data, vtable.as_ptr()) })
334 }
335
336 pub fn is_empty(&self) -> bool {
338 let Some(sequence) = self.to_packed::<SequenceElem>() else {
339 return false;
340 };
341
342 sequence.children.is_empty()
343 }
344
345 pub fn sequence_recursive_for_each<'a>(&'a self, f: &mut impl FnMut(&'a Self)) {
347 if let Some(sequence) = self.to_packed::<SequenceElem>() {
348 for child in &sequence.children {
349 child.sequence_recursive_for_each(f);
350 }
351 } else {
352 f(self);
353 }
354 }
355
356 pub fn styled_with_recipe(
358 self,
359 engine: &mut Engine,
360 context: Tracked<Context>,
361 recipe: Recipe,
362 ) -> SourceResult<Self> {
363 if recipe.selector().is_none() {
364 recipe.apply(engine, context, self)
365 } else {
366 Ok(self.styled(recipe))
367 }
368 }
369
370 pub fn repeat(&self, count: usize) -> Self {
372 Self::sequence(std::iter::repeat_with(|| self.clone()).take(count))
373 }
374
375 pub fn styled(mut self, style: impl Into<Style>) -> Self {
377 if let Some(style_elem) = self.to_packed_mut::<StyledElem>() {
378 style_elem.styles.apply_one(style.into());
379 self
380 } else {
381 self.styled_with_map(style.into().into())
382 }
383 }
384
385 pub fn styled_with_map(mut self, styles: Styles) -> Self {
387 if styles.is_empty() {
388 return self;
389 }
390
391 if let Some(style_elem) = self.to_packed_mut::<StyledElem>() {
392 style_elem.styles.apply(styles);
393 self
394 } else {
395 StyledElem::new(self, styles).into()
396 }
397 }
398
399 pub fn style_in_place(&mut self, styles: Styles) {
401 if styles.is_empty() {
402 return;
403 }
404
405 if let Some(style_elem) = self.to_packed_mut::<StyledElem>() {
406 style_elem.styles.apply(styles);
407 } else {
408 *self = StyledElem::new(std::mem::take(self), styles).into();
409 }
410 }
411
412 pub fn query(&self, selector: Selector) -> Vec<Content> {
416 let mut results = Vec::new();
417 self.traverse(&mut |element| {
418 if selector.matches(&element, None) {
419 results.push(element);
420 }
421 });
422 results
423 }
424
425 pub fn query_first(&self, selector: &Selector) -> Option<Content> {
430 let mut result = None;
431 self.traverse(&mut |element| {
432 if result.is_none() && selector.matches(&element, None) {
433 result = Some(element);
434 }
435 });
436 result
437 }
438
439 pub fn plain_text(&self) -> EcoString {
441 let mut text = EcoString::new();
442 self.traverse(&mut |element| {
443 if let Some(textable) = element.with::<dyn PlainText>() {
444 textable.plain_text(&mut text);
445 }
446 });
447 text
448 }
449
450 fn traverse<F>(&self, f: &mut F)
452 where
453 F: FnMut(Content),
454 {
455 f(self.clone());
456
457 self.inner
458 .elem
459 .fields()
460 .into_iter()
461 .for_each(|(_, value)| walk_value(value, f));
462
463 fn walk_value<F>(value: Value, f: &mut F)
465 where
466 F: FnMut(Content),
467 {
468 match value {
469 Value::Content(content) => content.traverse(f),
470 Value::Array(array) => {
471 for value in array {
472 walk_value(value, f);
473 }
474 }
475 _ => {}
476 }
477 }
478 }
479}
480
481impl Content {
482 pub fn strong(self) -> Self {
484 let span = self.span();
485 StrongElem::new(self).pack().spanned(span)
486 }
487
488 pub fn emph(self) -> Self {
490 let span = self.span();
491 EmphElem::new(self).pack().spanned(span)
492 }
493
494 pub fn underlined(self) -> Self {
496 let span = self.span();
497 UnderlineElem::new(self).pack().spanned(span)
498 }
499
500 pub fn linked(self, dest: Destination) -> Self {
502 self.styled(LinkElem::set_current(Some(dest)))
503 }
504
505 pub fn aligned(self, align: Alignment) -> Self {
507 self.styled(AlignElem::set_alignment(align))
508 }
509
510 pub fn padded(self, padding: Sides<Rel<Length>>) -> Self {
512 let span = self.span();
513 PadElem::new(self)
514 .with_left(padding.left)
515 .with_top(padding.top)
516 .with_right(padding.right)
517 .with_bottom(padding.bottom)
518 .pack()
519 .spanned(span)
520 }
521
522 pub fn moved(self, delta: Axes<Rel<Length>>) -> Self {
524 let span = self.span();
525 MoveElem::new(self)
526 .with_dx(delta.x)
527 .with_dy(delta.y)
528 .pack()
529 .spanned(span)
530 }
531}
532
533#[scope]
534impl Content {
535 #[func]
541 pub fn func(&self) -> Element {
542 self.elem()
543 }
544
545 #[func]
547 pub fn has(
548 &self,
549 field: Str,
551 ) -> bool {
552 if field.as_str() == "label" {
553 return self.label().is_some();
554 }
555
556 let Some(id) = self.elem().field_id(&field) else {
557 return false;
558 };
559
560 self.inner.elem.has(id)
561 }
562
563 #[func]
567 pub fn at(
568 &self,
569 field: Str,
571 #[named]
573 default: Option<Value>,
574 ) -> StrResult<Value> {
575 self.get_by_name(&field)
576 .or_else(|e| default.ok_or(e))
577 .map_err(|e| e.message_no_default(self, &field))
578 }
579
580 #[func]
589 pub fn fields(&self) -> Dict {
590 let mut dict = self.inner.elem.fields();
591 if let Some(label) = self.label() {
592 dict.insert("label".into(), label.into_value());
593 }
594 dict
595 }
596
597 #[func]
602 pub fn location(&self) -> Option<Location> {
603 self.inner.location
604 }
605}
606
607impl Default for Content {
608 fn default() -> Self {
609 Self::empty()
610 }
611}
612
613impl Debug for Content {
614 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
615 self.inner.elem.fmt(f)
616 }
617}
618
619impl<T: NativeElement> From<T> for Content {
620 fn from(value: T) -> Self {
621 Self::new(value)
622 }
623}
624
625impl PartialEq for Content {
626 fn eq(&self, other: &Self) -> bool {
627 self.elem() == other.elem() && self.inner.elem.dyn_eq(other)
629 }
630}
631
632impl Repr for Content {
633 fn repr(&self) -> EcoString {
634 self.inner.elem.repr()
635 }
636}
637
638impl Add for Content {
639 type Output = Self;
640
641 fn add(self, mut rhs: Self) -> Self::Output {
642 let mut lhs = self;
643 match (lhs.to_packed_mut::<SequenceElem>(), rhs.to_packed_mut::<SequenceElem>()) {
644 (Some(seq_lhs), Some(rhs)) => {
645 seq_lhs.children.extend(rhs.children.iter().cloned());
646 lhs
647 }
648 (Some(seq_lhs), None) => {
649 seq_lhs.children.push(rhs);
650 lhs
651 }
652 (None, Some(rhs_seq)) => {
653 rhs_seq.children.insert(0, lhs);
654 rhs
655 }
656 (None, None) => Self::sequence([lhs, rhs]),
657 }
658 }
659}
660
661impl<'a> Add<&'a Self> for Content {
662 type Output = Self;
663
664 fn add(self, rhs: &'a Self) -> Self::Output {
665 let mut lhs = self;
666 match (lhs.to_packed_mut::<SequenceElem>(), rhs.to_packed::<SequenceElem>()) {
667 (Some(seq_lhs), Some(rhs)) => {
668 seq_lhs.children.extend(rhs.children.iter().cloned());
669 lhs
670 }
671 (Some(seq_lhs), None) => {
672 seq_lhs.children.push(rhs.clone());
673 lhs
674 }
675 (None, Some(_)) => {
676 let mut rhs = rhs.clone();
677 rhs.to_packed_mut::<SequenceElem>().unwrap().children.insert(0, lhs);
678 rhs
679 }
680 (None, None) => Self::sequence([lhs, rhs.clone()]),
681 }
682 }
683}
684
685impl AddAssign for Content {
686 fn add_assign(&mut self, rhs: Self) {
687 *self = std::mem::take(self) + rhs;
688 }
689}
690
691impl AddAssign<&Self> for Content {
692 fn add_assign(&mut self, rhs: &Self) {
693 *self = std::mem::take(self) + rhs;
694 }
695}
696
697impl Sum for Content {
698 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
699 Self::sequence(iter)
700 }
701}
702
703impl Serialize for Content {
704 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
705 where
706 S: Serializer,
707 {
708 serializer.collect_map(
709 iter::once(("func".into(), self.func().name().into_value()))
710 .chain(self.fields()),
711 )
712 }
713}
714
715trait Bounds: Debug + Repr + Fields + Send + Sync + 'static {
717 fn dyn_type_id(&self) -> TypeId;
718 fn dyn_elem(&self) -> Element;
719 fn dyn_clone(&self, inner: &Inner<dyn Bounds>, span: Span) -> Content;
720 fn dyn_hash(&self, hasher: &mut dyn Hasher);
721 fn dyn_eq(&self, other: &Content) -> bool;
722}
723
724impl<T: NativeElement> Bounds for T {
725 fn dyn_type_id(&self) -> TypeId {
726 TypeId::of::<Self>()
727 }
728
729 fn dyn_elem(&self) -> Element {
730 Self::elem()
731 }
732
733 fn dyn_clone(&self, inner: &Inner<dyn Bounds>, span: Span) -> Content {
734 Content {
735 inner: Arc::new(Inner {
736 label: inner.label,
737 location: inner.location,
738 lifecycle: inner.lifecycle.clone(),
739 elem: LazyHash::reuse(self.clone(), &inner.elem),
740 }),
741 span,
742 }
743 }
744
745 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
746 TypeId::of::<Self>().hash(&mut state);
747 self.hash(&mut state);
748 }
749
750 fn dyn_eq(&self, other: &Content) -> bool {
751 let Some(other) = other.to_packed::<Self>() else {
752 return false;
753 };
754 *self == **other
755 }
756}
757
758impl Hash for dyn Bounds {
759 fn hash<H: Hasher>(&self, state: &mut H) {
760 self.dyn_hash(state);
761 }
762}
763
764#[derive(Clone, PartialEq, Hash)]
766#[repr(transparent)]
767pub struct Packed<T: NativeElement>(
768 Content,
770 PhantomData<T>,
771);
772
773impl<T: NativeElement> Packed<T> {
774 pub fn new(element: T) -> Self {
776 Packed(element.pack(), PhantomData)
778 }
779
780 pub fn from_ref(content: &Content) -> Option<&Self> {
782 if content.is::<T>() {
783 return Some(unsafe { std::mem::transmute::<&Content, &Packed<T>>(content) });
787 }
788 None
789 }
790
791 pub fn from_mut(content: &mut Content) -> Option<&mut Self> {
793 if content.is::<T>() {
794 return Some(unsafe {
798 std::mem::transmute::<&mut Content, &mut Packed<T>>(content)
799 });
800 }
801 None
802 }
803
804 pub fn from_owned(content: Content) -> Result<Self, Content> {
806 if content.is::<T>() {
807 return Ok(unsafe { std::mem::transmute::<Content, Packed<T>>(content) });
811 }
812 Err(content)
813 }
814
815 pub fn pack(self) -> Content {
817 self.0
818 }
819
820 pub fn unpack(self) -> T {
822 (*self).clone()
824 }
825
826 pub fn span(&self) -> Span {
828 self.0.span()
829 }
830
831 pub fn spanned(self, span: Span) -> Self {
833 Self(self.0.spanned(span), PhantomData)
834 }
835
836 pub fn label(&self) -> Option<Label> {
838 self.0.label()
839 }
840
841 pub fn location(&self) -> Option<Location> {
843 self.0.location()
844 }
845
846 pub fn set_location(&mut self, location: Location) {
848 self.0.set_location(location);
849 }
850}
851
852impl<T: NativeElement> AsRef<T> for Packed<T> {
853 fn as_ref(&self) -> &T {
854 self
855 }
856}
857
858impl<T: NativeElement> AsMut<T> for Packed<T> {
859 fn as_mut(&mut self) -> &mut T {
860 self
861 }
862}
863
864impl<T: NativeElement> Deref for Packed<T> {
865 type Target = T;
866
867 fn deref(&self) -> &Self::Target {
868 let elem = &*self.0.inner.elem;
874 unsafe { &*(elem as *const dyn Bounds as *const T) }
875 }
876}
877
878impl<T: NativeElement> DerefMut for Packed<T> {
879 fn deref_mut(&mut self) -> &mut Self::Target {
880 let elem = &mut *self.0.make_mut().elem;
887 unsafe { &mut *(elem as *mut dyn Bounds as *mut T) }
888 }
889}
890
891impl<T: NativeElement + Debug> Debug for Packed<T> {
892 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
893 self.0.fmt(f)
894 }
895}
896
897#[elem(Debug, Repr, PartialEq)]
899pub struct SequenceElem {
900 #[required]
902 pub children: Vec<Content>,
903}
904
905impl Debug for SequenceElem {
906 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
907 write!(f, "Sequence ")?;
908 f.debug_list().entries(&self.children).finish()
909 }
910}
911
912#[allow(clippy::derivable_impls)]
914impl Default for SequenceElem {
915 fn default() -> Self {
916 Self { children: Default::default() }
917 }
918}
919
920impl PartialEq for SequenceElem {
921 fn eq(&self, other: &Self) -> bool {
922 self.children.iter().eq(other.children.iter())
923 }
924}
925
926impl Repr for SequenceElem {
927 fn repr(&self) -> EcoString {
928 if self.children.is_empty() {
929 "[]".into()
930 } else {
931 let elements = crate::foundations::repr::pretty_array_like(
932 &self.children.iter().map(|c| c.inner.elem.repr()).collect::<Vec<_>>(),
933 false,
934 );
935 eco_format!("sequence{}", elements)
936 }
937 }
938}
939
940#[elem(Debug, Repr, PartialEq)]
942pub struct StyledElem {
943 #[required]
945 pub child: Content,
946 #[required]
948 pub styles: Styles,
949}
950
951impl Debug for StyledElem {
952 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
953 for style in self.styles.iter() {
954 writeln!(f, "#{style:?}")?;
955 }
956 self.child.fmt(f)
957 }
958}
959
960impl PartialEq for StyledElem {
961 fn eq(&self, other: &Self) -> bool {
962 self.child == other.child
963 }
964}
965
966impl Repr for StyledElem {
967 fn repr(&self) -> EcoString {
968 eco_format!("styled(child: {}, ..)", self.child.repr())
969 }
970}
971
972pub trait PlainText {
974 fn plain_text(&self, text: &mut EcoString);
976}
977
978#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
980pub enum FieldAccessError {
981 Unknown,
982 Unset,
983 Internal,
984}
985
986impl FieldAccessError {
987 #[cold]
989 pub fn message(self, content: &Content, field: &str) -> EcoString {
990 let elem_name = content.elem().name();
991 match self {
992 FieldAccessError::Unknown => {
993 eco_format!("{elem_name} does not have field {}", field.repr())
994 }
995 FieldAccessError::Unset => {
996 eco_format!(
997 "field {} in {elem_name} is not known at this point",
998 field.repr()
999 )
1000 }
1001 FieldAccessError::Internal => {
1002 eco_format!(
1003 "internal error when accessing field {} in {elem_name} – this is a bug",
1004 field.repr()
1005 )
1006 }
1007 }
1008 }
1009
1010 #[cold]
1012 pub fn message_no_default(self, content: &Content, field: &str) -> EcoString {
1013 let mut msg = self.message(content, field);
1014 msg.push_str(" and no default was specified");
1015 msg
1016 }
1017}