summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/value.rs43
1 files changed, 42 insertions, 1 deletions
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 6ce815a4..352906aa 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -8,7 +8,7 @@ use std::sync::Arc;
use super::{ops, Args, Array, Dict, Func, RawLength};
use crate::diag::{with_alternative, StrResult};
use crate::geom::{
- Angle, Color, Dir, Em, Fraction, Length, Paint, Ratio, Relative, RgbaColor,
+ Angle, Color, Dir, Em, Fraction, Length, Paint, Ratio, Relative, RgbaColor, Sides,
};
use crate::library::text::RawNode;
use crate::model::{Content, Layout, LayoutNode};
@@ -596,6 +596,47 @@ impl<T: Cast> Cast for Smart<T> {
}
}
+impl<T> Cast for Sides<T>
+where
+ T: Cast + Default + Clone,
+{
+ fn is(value: &Value) -> bool {
+ matches!(value, Value::Dict(_)) || T::is(value)
+ }
+
+ fn cast(value: Value) -> StrResult<Self> {
+ match value {
+ Value::Dict(dict) => {
+ for (key, _) in &dict {
+ if !matches!(
+ key.as_str(),
+ "left" | "top" | "right" | "bottom" | "x" | "y" | "rest"
+ ) {
+ return Err(format!("unexpected key {key:?}"));
+ }
+ }
+
+ let sides = Sides {
+ left: dict.get("left".into()).or_else(|_| dict.get("x".into())),
+ top: dict.get("top".into()).or_else(|_| dict.get("y".into())),
+ right: dict.get("right".into()).or_else(|_| dict.get("x".into())),
+ bottom: dict.get("bottom".into()).or_else(|_| dict.get("y".into())),
+ }
+ .map(|side| {
+ side.or_else(|_| dict.get("rest".into()))
+ .and_then(|v| T::cast(v.clone()))
+ .unwrap_or_default()
+ });
+
+ Ok(sides)
+ }
+ v => T::cast(v)
+ .map(Sides::splat)
+ .map_err(|msg| with_alternative(msg, "dictionary")),
+ }
+ }
+}
+
dynamic! {
Dir: "direction",
}