Skip to main content

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};
12
13use crate::diag::{HintedStrResult, HintedString, StrResult, WarningSink};
14use crate::foundations::{
15    Args, Array, AutoValue, Bytes, CastInfo, Content, Datetime, Decimal, Dict, Duration,
16    Fold, FromValue, Func, IntoValue, Label, Module, NativeElement, NativeType,
17    NoneValue, Reflect, Repr, Resolve, Scope, Str, Styles, Symbol, SymbolElem, Type,
18    Version, fields, ops, repr,
19};
20use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
21use crate::text::{RawContent, RawElem, TextElem};
22use crate::visualize::{Color, Gradient, Tiling};
23
24/// A computational value.
25#[derive(Default, Clone)]
26pub enum Value {
27    /// The value that indicates the absence of a meaningful value.
28    #[default]
29    None,
30    /// A value that indicates some smart default behaviour.
31    Auto,
32    /// A boolean: `true, false`.
33    Bool(bool),
34    /// An integer: `120`.
35    Int(i64),
36    /// A floating-point number: `1.2`, `10e-4`.
37    Float(f64),
38    /// A length: `12pt`, `3cm`, `1.5em`, `1em - 2pt`.
39    Length(Length),
40    /// An angle: `1.5rad`, `90deg`.
41    Angle(Angle),
42    /// A ratio: `50%`.
43    Ratio(Ratio),
44    /// A relative length, combination of a ratio and a length: `20% + 5cm`.
45    Relative(Rel<Length>),
46    /// A fraction: `1fr`.
47    Fraction(Fr),
48    /// A color value: `#f79143ff`.
49    Color(Color),
50    /// A gradient value: `gradient.linear(...)`.
51    Gradient(Gradient),
52    /// A tiling fill: `tiling(...)`.
53    Tiling(Tiling),
54    /// A symbol: `arrow.l`.
55    Symbol(Symbol),
56    /// A version.
57    Version(Version),
58    /// A string: `"string"`.
59    Str(Str),
60    /// Raw bytes.
61    Bytes(Bytes),
62    /// A label: `<intro>`.
63    Label(Label),
64    /// A datetime
65    Datetime(Datetime),
66    /// A decimal value: `decimal("123.4500")`
67    Decimal(Decimal),
68    /// A duration
69    Duration(Duration),
70    /// A content value: `[*Hi* there]`.
71    Content(Content),
72    // Content styles.
73    Styles(Styles),
74    /// An array of values: `(1, "hi", 12cm)`.
75    Array(Array),
76    /// A dictionary value: `(a: 1, b: "hi")`.
77    Dict(Dict),
78    /// An executable function.
79    Func(Func),
80    /// Captured arguments to a function.
81    Args(Args),
82    /// A type.
83    Type(Type),
84    /// A module.
85    Module(Module),
86    /// A dynamic value.
87    Dyn(Dynamic),
88}
89
90impl Value {
91    /// Create a new dynamic value.
92    pub fn dynamic<T>(any: T) -> Self
93    where
94        T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
95    {
96        Self::Dyn(Dynamic::new(any))
97    }
98
99    /// Create a numeric value from a number with a unit.
100    pub fn numeric(pair: (f64, ast::Unit)) -> Self {
101        let (v, unit) = pair;
102        match unit {
103            ast::Unit::Pt => Abs::pt(v).into_value(),
104            ast::Unit::Mm => Abs::mm(v).into_value(),
105            ast::Unit::Cm => Abs::cm(v).into_value(),
106            ast::Unit::In => Abs::inches(v).into_value(),
107            ast::Unit::Rad => Angle::rad(v).into_value(),
108            ast::Unit::Deg => Angle::deg(v).into_value(),
109            ast::Unit::Em => Em::new(v).into_value(),
110            ast::Unit::Fr => Fr::new(v).into_value(),
111            ast::Unit::Percent => Ratio::new(v / 100.0).into_value(),
112        }
113    }
114
115    /// The type of this value.
116    pub fn ty(&self) -> Type {
117        match self {
118            Self::None => Type::of::<NoneValue>(),
119            Self::Auto => Type::of::<AutoValue>(),
120            Self::Bool(_) => Type::of::<bool>(),
121            Self::Int(_) => Type::of::<i64>(),
122            Self::Float(_) => Type::of::<f64>(),
123            Self::Length(_) => Type::of::<Length>(),
124            Self::Angle(_) => Type::of::<Angle>(),
125            Self::Ratio(_) => Type::of::<Ratio>(),
126            Self::Relative(_) => Type::of::<Rel<Length>>(),
127            Self::Fraction(_) => Type::of::<Fr>(),
128            Self::Color(_) => Type::of::<Color>(),
129            Self::Gradient(_) => Type::of::<Gradient>(),
130            Self::Tiling(_) => Type::of::<Tiling>(),
131            Self::Symbol(_) => Type::of::<Symbol>(),
132            Self::Version(_) => Type::of::<Version>(),
133            Self::Str(_) => Type::of::<Str>(),
134            Self::Bytes(_) => Type::of::<Bytes>(),
135            Self::Label(_) => Type::of::<Label>(),
136            Self::Datetime(_) => Type::of::<Datetime>(),
137            Self::Decimal(_) => Type::of::<Decimal>(),
138            Self::Duration(_) => Type::of::<Duration>(),
139            Self::Content(_) => Type::of::<Content>(),
140            Self::Styles(_) => Type::of::<Styles>(),
141            Self::Array(_) => Type::of::<Array>(),
142            Self::Dict(_) => Type::of::<Dict>(),
143            Self::Func(_) => Type::of::<Func>(),
144            Self::Args(_) => Type::of::<Args>(),
145            Self::Type(_) => Type::of::<Type>(),
146            Self::Module(_) => Type::of::<Module>(),
147            Self::Dyn(v) => v.ty(),
148        }
149    }
150
151    /// Try to cast the value into a specific type.
152    pub fn cast<T: FromValue>(self) -> HintedStrResult<T> {
153        T::from_value(self)
154    }
155
156    /// Try to access a field on the value.
157    pub fn field(&self, field: &str, sink: impl WarningSink) -> StrResult<Value> {
158        match self {
159            Self::Symbol(symbol) => {
160                symbol.clone().modified(sink, field).map(Self::Symbol)
161            }
162            Self::Version(version) => version.component(field).map(Self::Int),
163            Self::Dict(dict) => dict.get(field).cloned(),
164            Self::Args(args) => args.field(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)]
497pub struct Dynamic(Arc<dyn Bounds>);
498
499impl Dynamic {
500    /// Create a new instance from any value that satisfies the required bounds.
501    pub fn new<T>(any: T) -> Self
502    where
503        T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
504    {
505        Self(Arc::new(any))
506    }
507
508    /// Whether the wrapped type is `T`.
509    pub fn is<T: 'static>(&self) -> bool {
510        let inner: &dyn Bounds = &*self.0;
511        (inner as &dyn 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        let inner: &dyn Bounds = &*self.0;
517        (inner as &dyn Any).downcast_ref()
518    }
519
520    /// The name of the stored value's type.
521    pub fn ty(&self) -> Type {
522        self.0.dyn_ty()
523    }
524}
525
526impl Debug for Dynamic {
527    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
528        self.0.fmt(f)
529    }
530}
531
532impl Repr for Dynamic {
533    fn repr(&self) -> EcoString {
534        self.0.repr()
535    }
536}
537
538impl PartialEq for Dynamic {
539    fn eq(&self, other: &Self) -> bool {
540        self.0.dyn_eq(other)
541    }
542}
543
544trait Bounds: Debug + Repr + Any + Sync + Send + 'static {
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 dyn_eq(&self, other: &Dynamic) -> bool {
555        let Some(other) = other.downcast::<Self>() else { return false };
556        self == other
557    }
558
559    fn dyn_ty(&self) -> Type {
560        Type::of::<T>()
561    }
562
563    fn dyn_hash(&self, mut state: &mut dyn Hasher) {
564        // Also hash the TypeId since values with different types but
565        // equal data should be different.
566        TypeId::of::<Self>().hash(&mut state);
567        self.hash(&mut state);
568    }
569}
570
571impl Hash for dyn Bounds {
572    fn hash<H: Hasher>(&self, state: &mut H) {
573        self.dyn_hash(state);
574    }
575}
576
577/// Implements traits for primitives (Value enum variants).
578macro_rules! primitive {
579    (
580        $ty:ty: $name:literal, $variant:ident
581        $(, $other:ident$(($binding:ident))? => $out:expr)*
582    ) => {
583        impl Reflect for $ty {
584            fn input() -> CastInfo {
585                CastInfo::Type(Type::of::<Self>())
586            }
587
588            fn output() -> CastInfo {
589                CastInfo::Type(Type::of::<Self>())
590            }
591
592            fn castable(value: &Value) -> bool {
593                matches!(value, Value::$variant(_)
594                    $(|  primitive!(@$other $(($binding))?))*)
595            }
596        }
597
598        impl IntoValue for $ty {
599            fn into_value(self) -> Value {
600                Value::$variant(self)
601            }
602        }
603
604        impl FromValue for $ty {
605            fn from_value(value: Value) -> HintedStrResult<Self> {
606                match value {
607                    Value::$variant(v) => Ok(v),
608                    $(Value::$other$(($binding))? => Ok($out),)*
609                    v => Err(<Self as Reflect>::error(&v)),
610                }
611            }
612        }
613    };
614
615    (@$other:ident($binding:ident)) => { Value::$other(_) };
616    (@$other:ident) => { Value::$other };
617}
618
619primitive! { bool: "boolean", Bool }
620primitive! { i64: "integer", Int }
621primitive! { f64: "float", Float, Int(v) => v as f64 }
622primitive! { Length: "length", Length }
623primitive! { Angle: "angle", Angle }
624primitive! { Ratio: "ratio", Ratio }
625primitive! { Rel<Length>:  "relative length",
626    Relative,
627    Length(v) => v.into(),
628    Ratio(v) => v.into()
629}
630primitive! { Fr: "fraction", Fraction }
631primitive! { Color: "color", Color }
632primitive! { Gradient: "gradient", Gradient }
633primitive! { Tiling: "tiling", Tiling }
634primitive! { Symbol: "symbol", Symbol }
635primitive! { Version: "version", Version }
636primitive! {
637    Str: "string",
638    Str,
639    Symbol(symbol) => symbol.get().into()
640}
641primitive! { Bytes: "bytes", Bytes }
642primitive! { Label: "label", Label }
643primitive! { Datetime: "datetime", Datetime }
644primitive! { Decimal: "decimal", Decimal }
645primitive! { Duration: "duration", Duration }
646primitive! { Content: "content",
647    Content,
648    None => Content::empty(),
649    Symbol(v) => SymbolElem::packed(v.get()),
650    Str(v) => TextElem::packed(v)
651}
652primitive! { Styles: "styles", Styles }
653primitive! { Array: "array", Array }
654primitive! { Dict: "dictionary", Dict }
655primitive! {
656    Func: "function",
657    Func,
658    Type(ty) => ty.constructor()?.clone(),
659    Symbol(symbol) => symbol.func()?
660}
661primitive! { Args: "arguments", Args }
662primitive! { Type: "type", Type }
663primitive! { Module: "module", Module }
664
665impl<T: Reflect> Reflect for Arc<T> {
666    fn input() -> CastInfo {
667        T::input()
668    }
669
670    fn output() -> CastInfo {
671        T::output()
672    }
673
674    fn castable(value: &Value) -> bool {
675        T::castable(value)
676    }
677
678    fn error(found: &Value) -> HintedString {
679        T::error(found)
680    }
681}
682
683impl<T: Clone + IntoValue> IntoValue for Arc<T> {
684    fn into_value(self) -> Value {
685        Arc::unwrap_or_clone(self).into_value()
686    }
687}
688
689impl<T: FromValue> FromValue for Arc<T> {
690    fn from_value(value: Value) -> HintedStrResult<Self> {
691        match value {
692            v if T::castable(&v) => Ok(Arc::new(T::from_value(v)?)),
693            _ => Err(Self::error(&value)),
694        }
695    }
696}
697
698impl<T: Clone + Resolve> Resolve for Arc<T> {
699    type Output = Arc<T::Output>;
700
701    fn resolve(self, styles: super::StyleChain) -> Self::Output {
702        Arc::new(Arc::unwrap_or_clone(self).resolve(styles))
703    }
704}
705
706impl<T: Clone + Fold> Fold for Arc<T> {
707    fn fold(self, outer: Self) -> Self {
708        Arc::new(Arc::unwrap_or_clone(self).fold(Arc::unwrap_or_clone(outer)))
709    }
710}
711
712#[cfg(test)]
713mod tests {
714    use super::*;
715    use crate::foundations::{array, dict};
716
717    #[track_caller]
718    fn test(value: impl IntoValue, exp: &str) {
719        assert_eq!(value.into_value().repr(), exp);
720    }
721
722    #[test]
723    fn test_value_size() {
724        assert!(std::mem::size_of::<Value>() <= 32);
725    }
726
727    #[test]
728    fn test_value_debug() {
729        // Primitives.
730        test(Value::None, "none");
731        test(Value::Auto, "auto");
732        test(Value::None.ty(), "type(none)");
733        test(Value::Auto.ty(), "type(auto)");
734        test(false, "false");
735        test(12i64, "12");
736        test(3.24, "3.24");
737        test(Abs::pt(5.5), "5.5pt");
738        test(Angle::deg(90.0), "90deg");
739        test(Ratio::one() / 2.0, "50%");
740        test(Ratio::new(0.3) + Length::from(Abs::cm(2.0)), "30% + 56.69pt");
741        test(Fr::one() * 7.55, "7.55fr");
742
743        // Collections.
744        test("hello", r#""hello""#);
745        test("\n", r#""\n""#);
746        test("\\", r#""\\""#);
747        test("\"", r#""\"""#);
748        test(array![], "()");
749        test(array![Value::None], "(none,)");
750        test(array![1, 2], "(1, 2)");
751        test(dict![], "(:)");
752        test(dict!["one" => 1], "(one: 1)");
753        test(dict!["two" => false, "one" => 1], "(two: false, one: 1)");
754    }
755}