typst_library/foundations/
value.rs

1use std::any::{Any, TypeId};
2use std::cmp::Ordering;
3use std::fmt::{self, Debug, Formatter};
4use std::hash::{Hash, Hasher};
5use std::sync::Arc;
6
7use ecow::{EcoString, eco_format};
8use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
9use serde::de::{Error, MapAccess, SeqAccess, Visitor};
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11use typst_syntax::{Span, ast};
12use typst_utils::ArcExt;
13
14use crate::diag::{DeprecationSink, HintedStrResult, HintedString, StrResult};
15use crate::foundations::{
16    Args, Array, AutoValue, Bytes, CastInfo, Content, Datetime, Decimal, Dict, Duration,
17    Fold, FromValue, Func, IntoValue, Label, Module, NativeElement, NativeType,
18    NoneValue, Reflect, Repr, Resolve, Scope, Str, Styles, Symbol, SymbolElem, Type,
19    Version, fields, ops, repr,
20};
21use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
22use crate::text::{RawContent, RawElem, TextElem};
23use crate::visualize::{Color, Gradient, Tiling};
24
25/// A computational value.
26#[derive(Default, Clone)]
27pub enum Value {
28    /// The value that indicates the absence of a meaningful value.
29    #[default]
30    None,
31    /// A value that indicates some smart default behaviour.
32    Auto,
33    /// A boolean: `true, false`.
34    Bool(bool),
35    /// An integer: `120`.
36    Int(i64),
37    /// A floating-point number: `1.2`, `10e-4`.
38    Float(f64),
39    /// A length: `12pt`, `3cm`, `1.5em`, `1em - 2pt`.
40    Length(Length),
41    /// An angle: `1.5rad`, `90deg`.
42    Angle(Angle),
43    /// A ratio: `50%`.
44    Ratio(Ratio),
45    /// A relative length, combination of a ratio and a length: `20% + 5cm`.
46    Relative(Rel<Length>),
47    /// A fraction: `1fr`.
48    Fraction(Fr),
49    /// A color value: `#f79143ff`.
50    Color(Color),
51    /// A gradient value: `gradient.linear(...)`.
52    Gradient(Gradient),
53    /// A tiling fill: `tiling(...)`.
54    Tiling(Tiling),
55    /// A symbol: `arrow.l`.
56    Symbol(Symbol),
57    /// A version.
58    Version(Version),
59    /// A string: `"string"`.
60    Str(Str),
61    /// Raw bytes.
62    Bytes(Bytes),
63    /// A label: `<intro>`.
64    Label(Label),
65    /// A datetime
66    Datetime(Datetime),
67    /// A decimal value: `decimal("123.4500")`
68    Decimal(Decimal),
69    /// A duration
70    Duration(Duration),
71    /// A content value: `[*Hi* there]`.
72    Content(Content),
73    // Content styles.
74    Styles(Styles),
75    /// An array of values: `(1, "hi", 12cm)`.
76    Array(Array),
77    /// A dictionary value: `(a: 1, b: "hi")`.
78    Dict(Dict),
79    /// An executable function.
80    Func(Func),
81    /// Captured arguments to a function.
82    Args(Args),
83    /// A type.
84    Type(Type),
85    /// A module.
86    Module(Module),
87    /// A dynamic value.
88    Dyn(Dynamic),
89}
90
91impl Value {
92    /// Create a new dynamic value.
93    pub fn dynamic<T>(any: T) -> Self
94    where
95        T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
96    {
97        Self::Dyn(Dynamic::new(any))
98    }
99
100    /// Create a numeric value from a number with a unit.
101    pub fn numeric(pair: (f64, ast::Unit)) -> Self {
102        let (v, unit) = pair;
103        match unit {
104            ast::Unit::Pt => Abs::pt(v).into_value(),
105            ast::Unit::Mm => Abs::mm(v).into_value(),
106            ast::Unit::Cm => Abs::cm(v).into_value(),
107            ast::Unit::In => Abs::inches(v).into_value(),
108            ast::Unit::Rad => Angle::rad(v).into_value(),
109            ast::Unit::Deg => Angle::deg(v).into_value(),
110            ast::Unit::Em => Em::new(v).into_value(),
111            ast::Unit::Fr => Fr::new(v).into_value(),
112            ast::Unit::Percent => Ratio::new(v / 100.0).into_value(),
113        }
114    }
115
116    /// The type of this value.
117    pub fn ty(&self) -> Type {
118        match self {
119            Self::None => Type::of::<NoneValue>(),
120            Self::Auto => Type::of::<AutoValue>(),
121            Self::Bool(_) => Type::of::<bool>(),
122            Self::Int(_) => Type::of::<i64>(),
123            Self::Float(_) => Type::of::<f64>(),
124            Self::Length(_) => Type::of::<Length>(),
125            Self::Angle(_) => Type::of::<Angle>(),
126            Self::Ratio(_) => Type::of::<Ratio>(),
127            Self::Relative(_) => Type::of::<Rel<Length>>(),
128            Self::Fraction(_) => Type::of::<Fr>(),
129            Self::Color(_) => Type::of::<Color>(),
130            Self::Gradient(_) => Type::of::<Gradient>(),
131            Self::Tiling(_) => Type::of::<Tiling>(),
132            Self::Symbol(_) => Type::of::<Symbol>(),
133            Self::Version(_) => Type::of::<Version>(),
134            Self::Str(_) => Type::of::<Str>(),
135            Self::Bytes(_) => Type::of::<Bytes>(),
136            Self::Label(_) => Type::of::<Label>(),
137            Self::Datetime(_) => Type::of::<Datetime>(),
138            Self::Decimal(_) => Type::of::<Decimal>(),
139            Self::Duration(_) => Type::of::<Duration>(),
140            Self::Content(_) => Type::of::<Content>(),
141            Self::Styles(_) => Type::of::<Styles>(),
142            Self::Array(_) => Type::of::<Array>(),
143            Self::Dict(_) => Type::of::<Dict>(),
144            Self::Func(_) => Type::of::<Func>(),
145            Self::Args(_) => Type::of::<Args>(),
146            Self::Type(_) => Type::of::<Type>(),
147            Self::Module(_) => Type::of::<Module>(),
148            Self::Dyn(v) => v.ty(),
149        }
150    }
151
152    /// Try to cast the value into a specific type.
153    pub fn cast<T: FromValue>(self) -> HintedStrResult<T> {
154        T::from_value(self)
155    }
156
157    /// Try to access a field on the value.
158    pub fn field(&self, field: &str, sink: impl DeprecationSink) -> StrResult<Value> {
159        match self {
160            Self::Symbol(symbol) => {
161                symbol.clone().modified(sink, field).map(Self::Symbol)
162            }
163            Self::Version(version) => version.component(field).map(Self::Int),
164            Self::Dict(dict) => dict.get(field).cloned(),
165            Self::Content(content) => content.field_by_name(field),
166            Self::Type(ty) => ty.field(field, sink).cloned(),
167            Self::Func(func) => func.field(field, sink).cloned(),
168            Self::Module(module) => module.field(field, sink).cloned(),
169            _ => fields::field(self, field),
170        }
171    }
172
173    /// The associated scope, if this is a function, type, or module.
174    pub fn scope(&self) -> Option<&Scope> {
175        match self {
176            Self::Func(func) => func.scope(),
177            Self::Type(ty) => Some(ty.scope()),
178            Self::Module(module) => Some(module.scope()),
179            _ => None,
180        }
181    }
182
183    /// Try to extract documentation for the value.
184    pub fn docs(&self) -> Option<&'static str> {
185        match self {
186            Self::Func(func) => func.docs(),
187            Self::Type(ty) => Some(ty.docs()),
188            _ => None,
189        }
190    }
191
192    /// Return the display representation of the value.
193    pub fn display(self) -> Content {
194        match self {
195            Self::None => Content::empty(),
196            Self::Int(v) => TextElem::packed(repr::format_int_with_base(v, 10)),
197            Self::Float(v) => TextElem::packed(repr::display_float(v)),
198            Self::Decimal(v) => TextElem::packed(eco_format!("{v}")),
199            Self::Str(v) => TextElem::packed(v),
200            Self::Version(v) => TextElem::packed(eco_format!("{v}")),
201            Self::Symbol(v) => SymbolElem::packed(v.get()),
202            Self::Content(v) => v,
203            Self::Module(module) => module.content(),
204            _ => RawElem::new(RawContent::Text(self.repr()))
205                .with_lang(Some("typc".into()))
206                .with_block(false)
207                .pack(),
208        }
209    }
210
211    /// Attach a span to the value, if possible.
212    pub fn spanned(self, span: Span) -> Self {
213        match self {
214            Value::Content(v) => Value::Content(v.spanned(span)),
215            Value::Func(v) => Value::Func(v.spanned(span)),
216            v => v,
217        }
218    }
219}
220
221impl Debug for Value {
222    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
223        match self {
224            Self::None => Debug::fmt(&NoneValue, f),
225            Self::Auto => Debug::fmt(&AutoValue, f),
226            Self::Bool(v) => Debug::fmt(v, f),
227            Self::Int(v) => Debug::fmt(v, f),
228            Self::Float(v) => Debug::fmt(v, f),
229            Self::Length(v) => Debug::fmt(v, f),
230            Self::Angle(v) => Debug::fmt(v, f),
231            Self::Ratio(v) => Debug::fmt(v, f),
232            Self::Relative(v) => Debug::fmt(v, f),
233            Self::Fraction(v) => Debug::fmt(v, f),
234            Self::Color(v) => Debug::fmt(v, f),
235            Self::Gradient(v) => Debug::fmt(v, f),
236            Self::Tiling(v) => Debug::fmt(v, f),
237            Self::Symbol(v) => Debug::fmt(v, f),
238            Self::Version(v) => Debug::fmt(v, f),
239            Self::Str(v) => Debug::fmt(v, f),
240            Self::Bytes(v) => Debug::fmt(v, f),
241            Self::Label(v) => Debug::fmt(v, f),
242            Self::Datetime(v) => Debug::fmt(v, f),
243            Self::Decimal(v) => Debug::fmt(v, f),
244            Self::Duration(v) => Debug::fmt(v, f),
245            Self::Content(v) => Debug::fmt(v, f),
246            Self::Styles(v) => Debug::fmt(v, f),
247            Self::Array(v) => Debug::fmt(v, f),
248            Self::Dict(v) => Debug::fmt(v, f),
249            Self::Func(v) => Debug::fmt(v, f),
250            Self::Args(v) => Debug::fmt(v, f),
251            Self::Type(v) => Debug::fmt(v, f),
252            Self::Module(v) => Debug::fmt(v, f),
253            Self::Dyn(v) => Debug::fmt(v, f),
254        }
255    }
256}
257
258impl Repr for Value {
259    fn repr(&self) -> EcoString {
260        match self {
261            Self::None => NoneValue.repr(),
262            Self::Auto => AutoValue.repr(),
263            Self::Bool(v) => v.repr(),
264            Self::Int(v) => v.repr(),
265            Self::Float(v) => v.repr(),
266            Self::Length(v) => v.repr(),
267            Self::Angle(v) => v.repr(),
268            Self::Ratio(v) => v.repr(),
269            Self::Relative(v) => v.repr(),
270            Self::Fraction(v) => v.repr(),
271            Self::Color(v) => v.repr(),
272            Self::Gradient(v) => v.repr(),
273            Self::Tiling(v) => v.repr(),
274            Self::Symbol(v) => v.repr(),
275            Self::Version(v) => v.repr(),
276            Self::Str(v) => v.repr(),
277            Self::Bytes(v) => v.repr(),
278            Self::Label(v) => v.repr(),
279            Self::Datetime(v) => v.repr(),
280            Self::Decimal(v) => v.repr(),
281            Self::Duration(v) => v.repr(),
282            Self::Content(v) => v.repr(),
283            Self::Styles(v) => v.repr(),
284            Self::Array(v) => v.repr(),
285            Self::Dict(v) => v.repr(),
286            Self::Func(v) => v.repr(),
287            Self::Args(v) => v.repr(),
288            Self::Type(v) => v.repr(),
289            Self::Module(v) => v.repr(),
290            Self::Dyn(v) => v.repr(),
291        }
292    }
293}
294
295impl PartialEq for Value {
296    fn eq(&self, other: &Self) -> bool {
297        ops::equal(self, other)
298    }
299}
300
301impl PartialOrd for Value {
302    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
303        ops::compare(self, other).ok()
304    }
305}
306
307impl Hash for Value {
308    fn hash<H: Hasher>(&self, state: &mut H) {
309        std::mem::discriminant(self).hash(state);
310        match self {
311            Self::None => {}
312            Self::Auto => {}
313            Self::Bool(v) => v.hash(state),
314            Self::Int(v) => v.hash(state),
315            Self::Float(v) => v.to_bits().hash(state),
316            Self::Length(v) => v.hash(state),
317            Self::Angle(v) => v.hash(state),
318            Self::Ratio(v) => v.hash(state),
319            Self::Relative(v) => v.hash(state),
320            Self::Fraction(v) => v.hash(state),
321            Self::Color(v) => v.hash(state),
322            Self::Gradient(v) => v.hash(state),
323            Self::Tiling(v) => v.hash(state),
324            Self::Symbol(v) => v.hash(state),
325            Self::Version(v) => v.hash(state),
326            Self::Str(v) => v.hash(state),
327            Self::Bytes(v) => v.hash(state),
328            Self::Label(v) => v.hash(state),
329            Self::Content(v) => v.hash(state),
330            Self::Styles(v) => v.hash(state),
331            Self::Datetime(v) => v.hash(state),
332            Self::Decimal(v) => v.hash(state),
333            Self::Duration(v) => v.hash(state),
334            Self::Array(v) => v.hash(state),
335            Self::Dict(v) => v.hash(state),
336            Self::Func(v) => v.hash(state),
337            Self::Args(v) => v.hash(state),
338            Self::Type(v) => v.hash(state),
339            Self::Module(v) => v.hash(state),
340            Self::Dyn(v) => v.hash(state),
341        }
342    }
343}
344
345impl Serialize for Value {
346    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
347    where
348        S: Serializer,
349    {
350        match self {
351            Self::None => NoneValue.serialize(serializer),
352            Self::Bool(v) => v.serialize(serializer),
353            Self::Int(v) => v.serialize(serializer),
354            Self::Float(v) => v.serialize(serializer),
355            Self::Str(v) => v.serialize(serializer),
356            Self::Bytes(v) => v.serialize(serializer),
357            Self::Symbol(v) => v.serialize(serializer),
358            Self::Content(v) => v.serialize(serializer),
359            Self::Array(v) => v.serialize(serializer),
360            Self::Dict(v) => v.serialize(serializer),
361
362            // Fall back to repr() for other things.
363            other => serializer.serialize_str(&other.repr()),
364        }
365    }
366}
367
368impl<'de> Deserialize<'de> for Value {
369    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
370    where
371        D: Deserializer<'de>,
372    {
373        deserializer.deserialize_any(ValueVisitor)
374    }
375}
376
377/// Visitor for value deserialization.
378struct ValueVisitor;
379
380impl<'de> Visitor<'de> for ValueVisitor {
381    type Value = Value;
382
383    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
384        formatter.write_str("a Typst value")
385    }
386
387    fn visit_bool<E: Error>(self, v: bool) -> Result<Self::Value, E> {
388        Ok(v.into_value())
389    }
390
391    fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
392        Ok(v.into_value())
393    }
394
395    fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
396        Ok(v.into_value())
397    }
398
399    fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
400        Ok(v.into_value())
401    }
402
403    fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
404        Ok(v.into_value())
405    }
406
407    fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
408        Ok(v.into_value())
409    }
410
411    fn visit_u8<E: Error>(self, v: u8) -> Result<Self::Value, E> {
412        Ok(v.into_value())
413    }
414
415    fn visit_u16<E: Error>(self, v: u16) -> Result<Self::Value, E> {
416        Ok(v.into_value())
417    }
418
419    fn visit_u32<E: Error>(self, v: u32) -> Result<Self::Value, E> {
420        Ok(v.into_value())
421    }
422
423    fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
424        Ok(v.into_value())
425    }
426
427    fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
428        Ok(v.into_value())
429    }
430
431    fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
432        Ok((v as f64).into_value())
433    }
434
435    fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
436        Ok(v.into_value())
437    }
438
439    fn visit_char<E: Error>(self, v: char) -> Result<Self::Value, E> {
440        Ok(v.into_value())
441    }
442
443    fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
444        Ok(v.into_value())
445    }
446
447    fn visit_borrowed_str<E: Error>(self, v: &'de str) -> Result<Self::Value, E> {
448        Ok(v.into_value())
449    }
450
451    fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
452        Ok(v.into_value())
453    }
454
455    fn visit_bytes<E: Error>(self, v: &[u8]) -> Result<Self::Value, E> {
456        Ok(Bytes::new(v.to_vec()).into_value())
457    }
458
459    fn visit_borrowed_bytes<E: Error>(self, v: &'de [u8]) -> Result<Self::Value, E> {
460        Ok(Bytes::new(v.to_vec()).into_value())
461    }
462
463    fn visit_byte_buf<E: Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
464        Ok(Bytes::new(v).into_value())
465    }
466
467    fn visit_none<E: Error>(self) -> Result<Self::Value, E> {
468        Ok(Value::None)
469    }
470
471    fn visit_some<D: Deserializer<'de>>(
472        self,
473        deserializer: D,
474    ) -> Result<Self::Value, D::Error> {
475        Value::deserialize(deserializer)
476    }
477
478    fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
479        Ok(Value::None)
480    }
481
482    fn visit_seq<A: SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
483        Ok(Array::deserialize(SeqAccessDeserializer::new(seq))?.into_value())
484    }
485
486    fn visit_map<A: MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
487        let dict = Dict::deserialize(MapAccessDeserializer::new(map))?;
488        Ok(match Datetime::from_toml_dict(&dict) {
489            None => dict.into_value(),
490            Some(datetime) => datetime.into_value(),
491        })
492    }
493}
494
495/// A value that is not part of the built-in enum.
496#[derive(Clone, Hash)]
497#[allow(clippy::derived_hash_with_manual_eq)]
498pub struct Dynamic(Arc<dyn Bounds>);
499
500impl Dynamic {
501    /// Create a new instance from any value that satisfies the required bounds.
502    pub fn new<T>(any: T) -> Self
503    where
504        T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
505    {
506        Self(Arc::new(any))
507    }
508
509    /// Whether the wrapped type is `T`.
510    pub fn is<T: 'static>(&self) -> bool {
511        (*self.0).as_any().is::<T>()
512    }
513
514    /// Try to downcast to a reference to a specific type.
515    pub fn downcast<T: 'static>(&self) -> Option<&T> {
516        (*self.0).as_any().downcast_ref()
517    }
518
519    /// The name of the stored value's type.
520    pub fn ty(&self) -> Type {
521        self.0.dyn_ty()
522    }
523}
524
525impl Debug for Dynamic {
526    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
527        self.0.fmt(f)
528    }
529}
530
531impl Repr for Dynamic {
532    fn repr(&self) -> EcoString {
533        self.0.repr()
534    }
535}
536
537impl PartialEq for Dynamic {
538    fn eq(&self, other: &Self) -> bool {
539        self.0.dyn_eq(other)
540    }
541}
542
543trait Bounds: Debug + Repr + Sync + Send + 'static {
544    fn as_any(&self) -> &dyn Any;
545    fn dyn_eq(&self, other: &Dynamic) -> bool;
546    fn dyn_ty(&self) -> Type;
547    fn dyn_hash(&self, state: &mut dyn Hasher);
548}
549
550impl<T> Bounds for T
551where
552    T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
553{
554    fn as_any(&self) -> &dyn Any {
555        self
556    }
557
558    fn dyn_eq(&self, other: &Dynamic) -> bool {
559        let Some(other) = other.downcast::<Self>() else { return false };
560        self == other
561    }
562
563    fn dyn_ty(&self) -> Type {
564        Type::of::<T>()
565    }
566
567    fn dyn_hash(&self, mut state: &mut dyn Hasher) {
568        // Also hash the TypeId since values with different types but
569        // equal data should be different.
570        TypeId::of::<Self>().hash(&mut state);
571        self.hash(&mut state);
572    }
573}
574
575impl Hash for dyn Bounds {
576    fn hash<H: Hasher>(&self, state: &mut H) {
577        self.dyn_hash(state);
578    }
579}
580
581/// Implements traits for primitives (Value enum variants).
582macro_rules! primitive {
583    (
584        $ty:ty: $name:literal, $variant:ident
585        $(, $other:ident$(($binding:ident))? => $out:expr)*
586    ) => {
587        impl Reflect for $ty {
588            fn input() -> CastInfo {
589                CastInfo::Type(Type::of::<Self>())
590            }
591
592            fn output() -> CastInfo {
593                CastInfo::Type(Type::of::<Self>())
594            }
595
596            fn castable(value: &Value) -> bool {
597                matches!(value, Value::$variant(_)
598                    $(|  primitive!(@$other $(($binding))?))*)
599            }
600        }
601
602        impl IntoValue for $ty {
603            fn into_value(self) -> Value {
604                Value::$variant(self)
605            }
606        }
607
608        impl FromValue for $ty {
609            fn from_value(value: Value) -> HintedStrResult<Self> {
610                match value {
611                    Value::$variant(v) => Ok(v),
612                    $(Value::$other$(($binding))? => Ok($out),)*
613                    v => Err(<Self as Reflect>::error(&v)),
614                }
615            }
616        }
617    };
618
619    (@$other:ident($binding:ident)) => { Value::$other(_) };
620    (@$other:ident) => { Value::$other };
621}
622
623primitive! { bool: "boolean", Bool }
624primitive! { i64: "integer", Int }
625primitive! { f64: "float", Float, Int(v) => v as f64 }
626primitive! { Length: "length", Length }
627primitive! { Angle: "angle", Angle }
628primitive! { Ratio: "ratio", Ratio }
629primitive! { Rel<Length>:  "relative length",
630    Relative,
631    Length(v) => v.into(),
632    Ratio(v) => v.into()
633}
634primitive! { Fr: "fraction", Fraction }
635primitive! { Color: "color", Color }
636primitive! { Gradient: "gradient", Gradient }
637primitive! { Tiling: "tiling", Tiling }
638primitive! { Symbol: "symbol", Symbol }
639primitive! { Version: "version", Version }
640primitive! {
641    Str: "string",
642    Str,
643    Symbol(symbol) => symbol.get().into()
644}
645primitive! { Bytes: "bytes", Bytes }
646primitive! { Label: "label", Label }
647primitive! { Datetime: "datetime", Datetime }
648primitive! { Decimal: "decimal", Decimal }
649primitive! { Duration: "duration", Duration }
650primitive! { Content: "content",
651    Content,
652    None => Content::empty(),
653    Symbol(v) => SymbolElem::packed(v.get()),
654    Str(v) => TextElem::packed(v)
655}
656primitive! { Styles: "styles", Styles }
657primitive! { Array: "array", Array }
658primitive! { Dict: "dictionary", Dict }
659primitive! {
660    Func: "function",
661    Func,
662    Type(ty) => ty.constructor()?.clone(),
663    Symbol(symbol) => symbol.func()?
664}
665primitive! { Args: "arguments", Args }
666primitive! { Type: "type", Type }
667primitive! { Module: "module", Module }
668
669impl<T: Reflect> Reflect for Arc<T> {
670    fn input() -> CastInfo {
671        T::input()
672    }
673
674    fn output() -> CastInfo {
675        T::output()
676    }
677
678    fn castable(value: &Value) -> bool {
679        T::castable(value)
680    }
681
682    fn error(found: &Value) -> HintedString {
683        T::error(found)
684    }
685}
686
687impl<T: Clone + IntoValue> IntoValue for Arc<T> {
688    fn into_value(self) -> Value {
689        Arc::take(self).into_value()
690    }
691}
692
693impl<T: FromValue> FromValue for Arc<T> {
694    fn from_value(value: Value) -> HintedStrResult<Self> {
695        match value {
696            v if T::castable(&v) => Ok(Arc::new(T::from_value(v)?)),
697            _ => Err(Self::error(&value)),
698        }
699    }
700}
701
702impl<T: Clone + Resolve> Resolve for Arc<T> {
703    type Output = Arc<T::Output>;
704
705    fn resolve(self, styles: super::StyleChain) -> Self::Output {
706        Arc::new(Arc::take(self).resolve(styles))
707    }
708}
709
710impl<T: Clone + Fold> Fold for Arc<T> {
711    fn fold(self, outer: Self) -> Self {
712        Arc::new(Arc::take(self).fold(Arc::take(outer)))
713    }
714}
715
716#[cfg(test)]
717mod tests {
718    use super::*;
719    use crate::foundations::{array, dict};
720
721    #[track_caller]
722    fn test(value: impl IntoValue, exp: &str) {
723        assert_eq!(value.into_value().repr(), exp);
724    }
725
726    #[test]
727    fn test_value_size() {
728        assert!(std::mem::size_of::<Value>() <= 32);
729    }
730
731    #[test]
732    fn test_value_debug() {
733        // Primitives.
734        test(Value::None, "none");
735        test(Value::Auto, "auto");
736        test(Value::None.ty(), "type(none)");
737        test(Value::Auto.ty(), "type(auto)");
738        test(false, "false");
739        test(12i64, "12");
740        test(3.24, "3.24");
741        test(Abs::pt(5.5), "5.5pt");
742        test(Angle::deg(90.0), "90deg");
743        test(Ratio::one() / 2.0, "50%");
744        test(Ratio::new(0.3) + Length::from(Abs::cm(2.0)), "30% + 56.69pt");
745        test(Fr::one() * 7.55, "7.55fr");
746
747        // Collections.
748        test("hello", r#""hello""#);
749        test("\n", r#""\n""#);
750        test("\\", r#""\\""#);
751        test("\"", r#""\"""#);
752        test(array![], "()");
753        test(array![Value::None], "(none,)");
754        test(array![1, 2], "(1, 2)");
755        test(dict![], "(:)");
756        test(dict!["one" => 1], "(one: 1)");
757        test(dict!["two" => false, "one" => 1], "(two: false, one: 1)");
758    }
759}