use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use typst_syntax::Span; use crate::foundations::{Content, Label, NativeElement}; use crate::introspection::Location; /// A packed element of a static type. #[derive(Clone)] #[repr(transparent)] pub struct Packed( /// Invariant: Must be of type `T`. Content, PhantomData, ); impl Packed { /// Pack element while retaining its static type. pub fn new(element: T) -> Self { // Safety: The element is known to be of type `T`. Packed(element.pack(), PhantomData) } /// Try to cast type-erased content into a statically known packed element. pub fn from_ref(content: &Content) -> Option<&Self> { if content.is::() { // Safety: // - We have checked the type. // - Packed is repr(transparent). return Some(unsafe { std::mem::transmute::<&Content, &Packed>(content) }); } None } /// Try to cast type-erased content into a statically known packed element. pub fn from_mut(content: &mut Content) -> Option<&mut Self> { if content.is::() { // Safety: // - We have checked the type. // - Packed is repr(transparent). return Some(unsafe { std::mem::transmute::<&mut Content, &mut Packed>(content) }); } None } /// Try to cast type-erased content into a statically known packed element. pub fn from_owned(content: Content) -> Result { if content.is::() { // Safety: // - We have checked the type. // - Packed is repr(transparent). return Ok(unsafe { std::mem::transmute::>(content) }); } Err(content) } /// Pack back into content. pub fn pack(self) -> Content { self.0 } /// Extract the raw underlying element. pub fn unpack(self) -> T { // This function doesn't yet need owned self, but might in the future. (*self).clone() } /// The element's span. pub fn span(&self) -> Span { self.0.span() } /// Set the span of the element. pub fn spanned(self, span: Span) -> Self { Self(self.0.spanned(span), PhantomData) } /// Accesses the label of the element. pub fn label(&self) -> Option