use ecow::{EcoString, eco_format};
use typst_utils::{PicoStr, ResolvedPicoStr};
use crate::diag::StrResult;
use crate::foundations::{Repr, Str, bail, func, scope, ty};
#[ty(scope, cast)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Label(PicoStr);
impl Label {
pub fn new(name: PicoStr) -> Option<Self> {
const EMPTY: PicoStr = PicoStr::constant("");
(name != EMPTY).then_some(Self(name))
}
pub fn resolve(self) -> ResolvedPicoStr {
self.0.resolve()
}
pub fn into_inner(self) -> PicoStr {
self.0
}
}
#[scope]
impl Label {
#[func(constructor)]
pub fn construct(
name: Str,
) -> StrResult<Label> {
if name.is_empty() {
bail!("label name must not be empty");
}
Ok(Self(PicoStr::intern(name.as_str())))
}
}
impl Repr for Label {
fn repr(&self) -> EcoString {
let resolved = self.resolve();
if typst_syntax::is_valid_label_literal_id(&resolved) {
eco_format!("<{resolved}>")
} else {
eco_format!("label({})", resolved.repr())
}
}
}
impl From<Label> for PicoStr {
fn from(value: Label) -> Self {
value.into_inner()
}
}
pub trait Unlabellable {}