diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-06-06 21:13:59 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-06-06 22:06:16 +0200 |
| commit | fd417da04f7ca4b995de7f6510abafd3e9c31307 (patch) | |
| tree | 3675529c75ca7363701ac8ea306de2cc1d3cbcb3 /src/eval/none.rs | |
| parent | 168bdf35bd773e67343c965cb473492cc5cae9e7 (diff) | |
Improve value casting infrastructure
Diffstat (limited to 'src/eval/none.rs')
| -rw-r--r-- | src/eval/none.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/eval/none.rs b/src/eval/none.rs new file mode 100644 index 00000000..ab7644a7 --- /dev/null +++ b/src/eval/none.rs @@ -0,0 +1,74 @@ +use std::fmt::{self, Debug, Formatter}; + +use super::{cast, CastInfo, FromValue, IntoValue, Reflect, Value}; +use crate::diag::StrResult; + +/// A value that indicates the absence of any other value. +#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct NoneValue; + +impl Reflect for NoneValue { + fn describe() -> CastInfo { + CastInfo::Type("none") + } + + 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) -> StrResult<Self> { + 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") + } +} + +cast! { + (), + self => Value::None, + _: NoneValue => (), +} + +impl<T: Reflect> Reflect for Option<T> { + fn describe() -> CastInfo { + T::describe() + NoneValue::describe() + } + + fn castable(value: &Value) -> bool { + NoneValue::castable(value) || T::castable(value) + } +} + +impl<T: IntoValue> IntoValue for Option<T> { + fn into_value(self) -> Value { + match self { + Some(v) => v.into_value(), + None => Value::None, + } + } +} + +impl<T: FromValue> FromValue for Option<T> { + fn from_value(value: Value) -> StrResult<Self> { + match value { + Value::None => Ok(None), + v if T::castable(&v) => Ok(Some(T::from_value(v)?)), + _ => Err(Self::error(&value)), + } + } +} |
