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