typst_library/foundations/
none.rs

1use std::fmt::{self, Debug, Formatter};
2
3use ecow::EcoString;
4use serde::{Serialize, Serializer};
5
6use crate::diag::HintedStrResult;
7use crate::foundations::{
8    cast, ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value,
9};
10
11/// A value that indicates the absence of any other value.
12///
13/// The none type has exactly one value: `{none}`.
14///
15/// When inserted into the document, it is not visible. This is also the value
16/// that is produced by empty code blocks. It can be
17/// [joined]($scripting/#blocks) with any value, yielding the other value.
18///
19/// # Example
20/// ```example
21/// Not visible: #none
22/// ```
23#[ty(cast, name = "none")]
24#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
25pub struct NoneValue;
26
27impl Reflect for NoneValue {
28    fn input() -> CastInfo {
29        CastInfo::Type(Type::of::<Self>())
30    }
31
32    fn output() -> CastInfo {
33        CastInfo::Type(Type::of::<Self>())
34    }
35
36    fn castable(value: &Value) -> bool {
37        matches!(value, Value::None)
38    }
39}
40
41impl IntoValue for NoneValue {
42    fn into_value(self) -> Value {
43        Value::None
44    }
45}
46
47impl FromValue for NoneValue {
48    fn from_value(value: Value) -> HintedStrResult<Self> {
49        match value {
50            Value::None => Ok(Self),
51            _ => Err(Self::error(&value)),
52        }
53    }
54}
55
56impl Debug for NoneValue {
57    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
58        f.pad("None")
59    }
60}
61
62impl Repr for NoneValue {
63    fn repr(&self) -> EcoString {
64        "none".into()
65    }
66}
67
68impl Serialize for NoneValue {
69    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
70    where
71        S: Serializer,
72    {
73        serializer.serialize_none()
74    }
75}
76
77cast! {
78    (),
79    self => Value::None,
80    _: NoneValue => (),
81}
82
83impl<T: Reflect> Reflect for Option<T> {
84    fn input() -> CastInfo {
85        T::input() + NoneValue::input()
86    }
87
88    fn output() -> CastInfo {
89        T::output() + NoneValue::output()
90    }
91
92    fn castable(value: &Value) -> bool {
93        NoneValue::castable(value) || T::castable(value)
94    }
95}
96
97impl<T: IntoValue> IntoValue for Option<T> {
98    fn into_value(self) -> Value {
99        match self {
100            Some(v) => v.into_value(),
101            None => Value::None,
102        }
103    }
104}
105
106impl<T: FromValue> FromValue for Option<T> {
107    fn from_value(value: Value) -> HintedStrResult<Self> {
108        match value {
109            Value::None => Ok(None),
110            v if T::castable(&v) => Ok(Some(T::from_value(v)?)),
111            _ => Err(Self::error(&value)),
112        }
113    }
114}