summaryrefslogtreecommitdiff
path: root/src/geom/sides.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/geom/sides.rs')
-rw-r--r--src/geom/sides.rs81
1 files changed, 43 insertions, 38 deletions
diff --git a/src/geom/sides.rs b/src/geom/sides.rs
index a905a5f8..d4b72a9d 100644
--- a/src/geom/sides.rs
+++ b/src/geom/sides.rs
@@ -1,3 +1,5 @@
+use crate::eval::{CastInfo, FromValue, IntoValue, Reflect};
+
use super::*;
/// A container with left, top, right and bottom components.
@@ -178,19 +180,51 @@ impl Side {
}
}
-impl<T> Cast for Sides<Option<T>>
+impl<T: Reflect> Reflect for Sides<Option<T>> {
+ fn describe() -> CastInfo {
+ T::describe() + Dict::describe()
+ }
+
+ fn castable(value: &Value) -> bool {
+ Dict::castable(value) || T::castable(value)
+ }
+}
+
+impl<T> IntoValue for Sides<T>
where
- T: Default + Cast + Clone,
+ T: PartialEq + IntoValue,
{
- fn is(value: &Value) -> bool {
- matches!(value, Value::Dict(_)) || T::is(value)
+ fn into_value(self) -> Value {
+ if self.is_uniform() {
+ return self.left.into_value();
+ }
+
+ let mut dict = Dict::new();
+ let mut handle = |key: &str, component: T| {
+ let value = component.into_value();
+ if value != Value::None {
+ dict.insert(key.into(), value);
+ }
+ };
+
+ handle("left", self.left);
+ handle("top", self.top);
+ handle("right", self.right);
+ handle("bottom", self.bottom);
+
+ Value::Dict(dict)
}
+}
- fn cast(mut value: Value) -> StrResult<Self> {
+impl<T> FromValue for Sides<Option<T>>
+where
+ T: Default + FromValue + Clone,
+{
+ fn from_value(mut value: Value) -> StrResult<Self> {
let keys = ["left", "top", "right", "bottom", "x", "y", "rest"];
if let Value::Dict(dict) = &mut value {
if dict.iter().any(|(key, _)| keys.contains(&key.as_str())) {
- let mut take = |key| dict.take(key).ok().map(T::cast).transpose();
+ let mut take = |key| dict.take(key).ok().map(T::from_value).transpose();
let rest = take("rest")?;
let x = take("x")?.or_else(|| rest.clone());
let y = take("y")?.or_else(|| rest.clone());
@@ -206,43 +240,14 @@ where
}
}
- if T::is(&value) {
- Ok(Self::splat(Some(T::cast(value)?)))
+ if T::castable(&value) {
+ Ok(Self::splat(Some(T::from_value(value)?)))
} else {
- <Self as Cast>::error(value)
+ Err(Self::error(&value))
}
}
-
- fn describe() -> CastInfo {
- T::describe() + CastInfo::Type("dictionary")
- }
}
-impl<T> From<Sides<T>> for Value
-where
- T: PartialEq + Into<Value>,
-{
- fn from(sides: Sides<T>) -> Self {
- if sides.is_uniform() {
- return sides.left.into();
- }
-
- let mut dict = Dict::new();
- let mut handle = |key: &str, component: T| {
- let value = component.into();
- if value != Value::None {
- dict.insert(key.into(), value);
- }
- };
-
- handle("left", sides.left);
- handle("top", sides.top);
- handle("right", sides.right);
- handle("bottom", sides.bottom);
-
- Value::Dict(dict)
- }
-}
impl<T: Resolve> Resolve for Sides<T> {
type Output = Sides<T::Output>;