use std::fmt::{self, Debug, Formatter}; use ecow::EcoString; use serde::{Serialize, Serializer}; use crate::diag::HintedStrResult; use crate::foundations::{ cast, ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value, }; /// A value that indicates the absence of any other value. /// /// The none type has exactly one value: `{none}`. /// /// When inserted into the document, it is not visible. This is also the value /// that is produced by empty code blocks. It can be /// [joined]($scripting/#blocks) with any value, yielding the other value. /// /// # Example /// ```example /// Not visible: #none /// ``` #[ty(cast, name = "none")] #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct NoneValue; impl Reflect for NoneValue { fn input() -> CastInfo { CastInfo::Type(Type::of::()) } fn output() -> CastInfo { CastInfo::Type(Type::of::()) } fn castable(value: &Value) -> bool { matches!(value, Value::None) } } impl IntoValue for NoneValue { fn into_value(self) -> Value { Value::None } } impl FromValue for NoneValue { fn from_value(value: Value) -> HintedStrResult { match value { Value::None => Ok(Self), _ => Err(Self::error(&value)), } } } impl Debug for NoneValue { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.pad("None") } } impl Repr for NoneValue { fn repr(&self) -> EcoString { "none".into() } } impl Serialize for NoneValue { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_none() } } cast! { (), self => Value::None, _: NoneValue => (), } impl Reflect for Option { fn input() -> CastInfo { T::input() + NoneValue::input() } fn output() -> CastInfo { T::output() + NoneValue::output() } fn castable(value: &Value) -> bool { NoneValue::castable(value) || T::castable(value) } } impl IntoValue for Option { fn into_value(self) -> Value { match self { Some(v) => v.into_value(), None => Value::None, } } } impl FromValue for Option { fn from_value(value: Value) -> HintedStrResult { match value { Value::None => Ok(None), v if T::castable(&v) => Ok(Some(T::from_value(v)?)), _ => Err(Self::error(&value)), } } }