1use crate::expr::Expression;
2
3use super::{
4 delegate::{DelegateEvalContext, DelegateEvaluable, DelegateValue, Delegated},
5 ids::NodeId,
6 property::{PropertyExpression, PropertyValue},
7 vector,
8};
9
10#[derive(Debug, Clone)]
11pub enum Deferred<T> {
12 Value(T),
13 Expr(Expression),
14}
15
16impl<T> Deferred<T> {
17 pub fn value(value: T) -> Self {
18 Self::Value(value)
19 }
20
21 pub fn eval(
22 &self,
23 node_id: NodeId,
24 property_path: &str,
25 ctx: &crate::expr::ExpressionContext<'_>,
26 ) -> crate::Result<T>
27 where
28 T: DeferredValue,
29 {
30 T::eval_deferred(self, node_id, property_path, ctx)
31 }
32
33 pub fn to_property_value(&self) -> PropertyValue
34 where
35 T: DeferredValue,
36 {
37 match self {
38 Self::Value(value) => T::to_property_value(value),
39 Self::Expr(_) => {
40 panic!(
41 "Deferred::to_property_value called on expression; use to_property_expression"
42 )
43 }
44 }
45 }
46
47 pub fn to_property_expression(&self) -> PropertyExpression
48 where
49 T: DeferredValue,
50 {
51 match self {
52 Self::Value(value) => PropertyExpression::Value(T::to_property_value(value)),
53 Self::Expr(expr) => PropertyExpression::Expr(expr.clone()),
54 }
55 }
56
57 pub fn from_property_expression(value: PropertyExpression) -> crate::Result<Self>
58 where
59 T: DeferredValue,
60 {
61 match value {
62 PropertyExpression::Value(value) => T::from_property_value(value)
63 .map(Self::Value)
64 .ok_or_else(|| {
65 PropertyValue::invalid_type(
66 NodeId::new(0),
67 "",
68 T::property_kind_name(),
69 "property",
70 )
71 }),
72 PropertyExpression::Expr(expr) => Ok(Self::Expr(expr)),
73 }
74 }
75}
76
77impl<T> From<T> for Deferred<T> {
78 fn from(value: T) -> Self {
79 Self::Value(value)
80 }
81}
82
83impl Deferred<f64> {
84 pub fn resolve_float(
85 &self,
86 node_id: NodeId,
87 property_path: &str,
88 ctx: &crate::expr::ExpressionContext<'_>,
89 ) -> crate::Result<f64> {
90 self.eval(node_id, property_path, ctx)
91 }
92}
93
94impl Deferred<i64> {
95 pub fn resolve_int(
96 &self,
97 node_id: NodeId,
98 property_path: &str,
99 ctx: &crate::expr::ExpressionContext<'_>,
100 ) -> crate::Result<i64> {
101 self.eval(node_id, property_path, ctx)
102 }
103
104 pub fn resolve_float(
105 &self,
106 node_id: NodeId,
107 property_path: &str,
108 ctx: &crate::expr::ExpressionContext<'_>,
109 ) -> crate::Result<f64> {
110 self.eval(node_id, property_path, ctx)
111 .map(|value| value as f64)
112 }
113}
114
115impl Deferred<bool> {
116 pub fn resolve_bool(
117 &self,
118 node_id: NodeId,
119 property_path: &str,
120 ctx: &crate::expr::ExpressionContext<'_>,
121 ) -> crate::Result<bool> {
122 self.eval(node_id, property_path, ctx)
123 }
124}
125
126impl Deferred<String> {
127 pub fn resolve_string(
128 &self,
129 node_id: NodeId,
130 property_path: &str,
131 ctx: &crate::expr::ExpressionContext<'_>,
132 ) -> crate::Result<String> {
133 self.eval(node_id, property_path, ctx)
134 }
135}
136
137impl Deferred<[u8; 4]> {
138 pub fn resolve_color(
139 &self,
140 node_id: NodeId,
141 property_path: &str,
142 ctx: &crate::expr::ExpressionContext<'_>,
143 ) -> crate::Result<[u8; 4]> {
144 self.eval(node_id, property_path, ctx)
145 }
146}
147
148impl Deferred<vector::paint::Paint> {
149 pub fn resolve_paint(
150 &self,
151 node_id: NodeId,
152 property_path: &str,
153 ctx: &crate::expr::ExpressionContext<'_>,
154 ) -> crate::Result<vector::paint::Paint> {
155 self.eval(node_id, property_path, ctx)
156 }
157}
158
159impl Deferred<(f64, f64)> {
160 pub fn resolve_vec2(
161 &self,
162 node_id: NodeId,
163 property_path: &str,
164 ctx: &crate::expr::ExpressionContext<'_>,
165 ) -> crate::Result<(f64, f64)> {
166 self.eval(node_id, property_path, ctx)
167 }
168}
169
170#[cfg(feature = "json")]
171impl<'de, T> serde::Deserialize<'de> for Deferred<T>
172where
173 T: DeferredJsonValue,
174{
175 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
176 where
177 D: serde::Deserializer<'de>,
178 {
179 let value = serde_json::Value::deserialize(deserializer)?;
180 if let Some(text) = value.as_str()
181 && let Some(source) = text.strip_prefix('=')
182 {
183 return Expression::parse(source)
184 .map(Self::Expr)
185 .map_err(serde::de::Error::custom);
186 }
187 T::from_json_value(&value)
188 .map(Self::Value)
189 .map_err(serde::de::Error::custom)
190 }
191}
192
193#[cfg(feature = "json")]
194pub trait DeferredJsonValue: Sized {
195 fn from_json_value(value: &serde_json::Value) -> Result<Self, String>;
196}
197
198pub trait DeferredValue: Clone {
199 fn eval_deferred(
200 deferred: &Deferred<Self>,
201 node_id: NodeId,
202 property_path: &str,
203 ctx: &crate::expr::ExpressionContext<'_>,
204 ) -> crate::Result<Self>
205 where
206 Self: Sized;
207
208 fn to_property_value(value: &Self) -> PropertyValue;
209 fn from_property_value(value: PropertyValue) -> Option<Self>
210 where
211 Self: Sized;
212 fn property_kind_name() -> &'static str;
213}
214
215impl<T> DelegateEvaluable for Deferred<T>
216where
217 T: DeferredValue,
218{
219 type Evaluated = T;
220
221 fn eval(&self, ctx: &DelegateEvalContext<'_>) -> crate::Result<Self::Evaluated> {
222 Deferred::eval(self, ctx.node_id, ctx.property_path, ctx.expr)
223 }
224}
225
226impl<T> DelegateValue for Deferred<T>
227where
228 T: DeferredValue,
229{
230 fn to_property_value(&self) -> PropertyValue {
231 Deferred::to_property_value(self)
232 }
233
234 fn to_property_expression(&self) -> PropertyExpression {
235 Deferred::to_property_expression(self)
236 }
237
238 fn from_property_expression(value: PropertyExpression) -> crate::Result<Self> {
239 Deferred::from_property_expression(value)
240 }
241}
242
243macro_rules! impl_delegated_deferred {
244 ($($ty:ty),* $(,)?) => {
245 $(
246 impl Delegated for $ty {
247 type Delegate = Deferred<$ty>;
248
249 fn into_delegate(self) -> Self::Delegate {
250 Deferred::value(self)
251 }
252 }
253 )*
254 };
255}
256
257impl_delegated_deferred!(
258 f64,
259 f32,
260 i64,
261 u32,
262 u8,
263 bool,
264 String,
265 [u8; 4],
266 (f64, f64),
267 [f32; 2]
268);
269
270macro_rules! impl_deferred_float_expr {
271 ($ty:ty, $conv:expr) => {
272 impl DeferredValue for $ty {
273 fn eval_deferred(
274 deferred: &Deferred<Self>,
275 node_id: NodeId,
276 property_path: &str,
277 ctx: &crate::expr::ExpressionContext<'_>,
278 ) -> crate::Result<Self> {
279 match deferred {
280 Deferred::Value(value) => Ok(*value),
281 Deferred::Expr(expr) => {
282 expr.evaluate(ctx)?.as_f64().map($conv).ok_or_else(|| {
283 PropertyValue::invalid_type(
284 node_id,
285 property_path,
286 "Float",
287 "expression",
288 )
289 })
290 }
291 }
292 }
293
294 fn to_property_value(value: &Self) -> PropertyValue {
295 PropertyValue::Float(f64::from(*value))
296 }
297
298 fn from_property_value(value: PropertyValue) -> Option<Self> {
299 value.coerce_float().map($conv)
300 }
301
302 fn property_kind_name() -> &'static str {
303 "Float"
304 }
305 }
306 };
307}
308
309impl_deferred_float_expr!(f64, |value: f64| value);
310
311impl DeferredValue for f32 {
312 fn eval_deferred(
313 deferred: &Deferred<Self>,
314 node_id: NodeId,
315 property_path: &str,
316 ctx: &crate::expr::ExpressionContext<'_>,
317 ) -> crate::Result<Self> {
318 match deferred {
319 Deferred::Value(value) => Ok(*value),
320 Deferred::Expr(expr) => expr
321 .evaluate(ctx)?
322 .as_f64()
323 .map(|value| value as f32)
324 .ok_or_else(|| {
325 PropertyValue::invalid_type(node_id, property_path, "Float", "expression")
326 }),
327 }
328 }
329
330 fn to_property_value(value: &Self) -> PropertyValue {
331 PropertyValue::Float(f64::from(*value))
332 }
333
334 fn from_property_value(value: PropertyValue) -> Option<Self> {
335 value.coerce_float().map(|value| value as f32)
336 }
337
338 fn property_kind_name() -> &'static str {
339 "Float"
340 }
341}
342
343impl DeferredValue for i64 {
344 fn eval_deferred(
345 deferred: &Deferred<Self>,
346 node_id: NodeId,
347 property_path: &str,
348 ctx: &crate::expr::ExpressionContext<'_>,
349 ) -> crate::Result<Self> {
350 match deferred {
351 Deferred::Value(value) => Ok(*value),
352 Deferred::Expr(expr) => {
353 let value = expr.evaluate(ctx)?.as_f64().ok_or_else(|| {
354 PropertyValue::invalid_type(node_id, property_path, "Int", "expression")
355 })?;
356 Ok(value as i64)
357 }
358 }
359 }
360
361 fn to_property_value(value: &Self) -> PropertyValue {
362 PropertyValue::Int(*value)
363 }
364
365 fn from_property_value(value: PropertyValue) -> Option<Self> {
366 value.coerce_int()
367 }
368
369 fn property_kind_name() -> &'static str {
370 "Int"
371 }
372}
373
374impl DeferredValue for u32 {
375 fn eval_deferred(
376 deferred: &Deferred<Self>,
377 node_id: NodeId,
378 property_path: &str,
379 ctx: &crate::expr::ExpressionContext<'_>,
380 ) -> crate::Result<Self> {
381 let value = match deferred {
382 Deferred::Value(value) => i64::from(*value),
383 Deferred::Expr(expr) => expr.evaluate(ctx)?.as_f64().ok_or_else(|| {
384 PropertyValue::invalid_type(node_id, property_path, "UInt", "expression")
385 })? as i64,
386 };
387 u32::try_from(value)
388 .map_err(|_| PropertyValue::invalid_type(node_id, property_path, "UInt", "range"))
389 }
390
391 fn to_property_value(value: &Self) -> PropertyValue {
392 PropertyValue::Int(i64::from(*value))
393 }
394
395 fn from_property_value(value: PropertyValue) -> Option<Self> {
396 value
397 .coerce_int()
398 .and_then(|value| u32::try_from(value).ok())
399 }
400
401 fn property_kind_name() -> &'static str {
402 "UInt"
403 }
404}
405
406impl DeferredValue for u8 {
407 fn eval_deferred(
408 deferred: &Deferred<Self>,
409 node_id: NodeId,
410 property_path: &str,
411 ctx: &crate::expr::ExpressionContext<'_>,
412 ) -> crate::Result<Self> {
413 let value = match deferred {
414 Deferred::Value(value) => i64::from(*value),
415 Deferred::Expr(expr) => expr.evaluate(ctx)?.as_f64().ok_or_else(|| {
416 PropertyValue::invalid_type(node_id, property_path, "Int", "expression")
417 })? as i64,
418 };
419 u8::try_from(value)
420 .map_err(|_| PropertyValue::invalid_type(node_id, property_path, "U8", "range"))
421 }
422
423 fn to_property_value(value: &Self) -> PropertyValue {
424 PropertyValue::Int(i64::from(*value))
425 }
426
427 fn from_property_value(value: PropertyValue) -> Option<Self> {
428 value
429 .coerce_int()
430 .and_then(|value| u8::try_from(value).ok())
431 }
432
433 fn property_kind_name() -> &'static str {
434 "U8"
435 }
436}
437
438impl DeferredValue for bool {
439 fn eval_deferred(
440 deferred: &Deferred<Self>,
441 _node_id: NodeId,
442 _property_path: &str,
443 ctx: &crate::expr::ExpressionContext<'_>,
444 ) -> crate::Result<Self> {
445 match deferred {
446 Deferred::Value(value) => Ok(*value),
447 Deferred::Expr(expr) => Ok(expr.evaluate(ctx)?.as_bool()),
448 }
449 }
450
451 fn to_property_value(value: &Self) -> PropertyValue {
452 PropertyValue::Bool(*value)
453 }
454
455 fn from_property_value(value: PropertyValue) -> Option<Self> {
456 value.coerce_bool()
457 }
458
459 fn property_kind_name() -> &'static str {
460 "Bool"
461 }
462}
463
464impl DeferredValue for String {
465 fn eval_deferred(
466 deferred: &Deferred<Self>,
467 _node_id: NodeId,
468 _property_path: &str,
469 ctx: &crate::expr::ExpressionContext<'_>,
470 ) -> crate::Result<Self> {
471 match deferred {
472 Deferred::Value(value) => Ok(value.clone()),
473 Deferred::Expr(expr) => Ok(expr.evaluate(ctx)?.as_string()),
474 }
475 }
476
477 fn to_property_value(value: &Self) -> PropertyValue {
478 PropertyValue::String(value.clone())
479 }
480
481 fn from_property_value(value: PropertyValue) -> Option<Self> {
482 value.coerce_string()
483 }
484
485 fn property_kind_name() -> &'static str {
486 "String"
487 }
488}
489
490macro_rules! impl_deferred_literal {
491 ($ty:ty, $kind:literal, $variant:ident, $expr_err:literal) => {
492 impl DeferredValue for $ty {
493 fn eval_deferred(
494 deferred: &Deferred<Self>,
495 node_id: NodeId,
496 property_path: &str,
497 _ctx: &crate::expr::ExpressionContext<'_>,
498 ) -> crate::Result<Self> {
499 match deferred {
500 Deferred::Value(value) => Ok(*value),
501 Deferred::Expr(_) => Err(PropertyValue::invalid_type(
502 node_id,
503 property_path,
504 $expr_err,
505 "expression",
506 )),
507 }
508 }
509
510 fn to_property_value(value: &Self) -> PropertyValue {
511 PropertyValue::$variant(*value)
512 }
513
514 fn from_property_value(value: PropertyValue) -> Option<Self> {
515 match value {
516 PropertyValue::$variant(value) => Some(value),
517 _ => None,
518 }
519 }
520
521 fn property_kind_name() -> &'static str {
522 $kind
523 }
524 }
525 };
526}
527
528impl_deferred_literal!([u8; 4], "Color", Color, "Color");
529
530impl DeferredValue for vector::paint::Paint {
531 fn eval_deferred(
532 deferred: &Deferred<Self>,
533 node_id: NodeId,
534 property_path: &str,
535 _ctx: &crate::expr::ExpressionContext<'_>,
536 ) -> crate::Result<Self> {
537 match deferred {
538 Deferred::Value(value) => Ok(value.clone()),
539 Deferred::Expr(_) => Err(PropertyValue::invalid_type(
540 node_id,
541 property_path,
542 "Paint",
543 "expression",
544 )),
545 }
546 }
547
548 fn to_property_value(value: &Self) -> PropertyValue {
549 PropertyValue::Paint(value.clone())
550 }
551
552 fn from_property_value(value: PropertyValue) -> Option<Self> {
553 match value {
554 PropertyValue::Paint(value) => Some(value),
555 PropertyValue::Color(value) => Some(vector::paint::Paint::solid(value)),
556 _ => None,
557 }
558 }
559
560 fn property_kind_name() -> &'static str {
561 "Paint"
562 }
563}
564
565impl_deferred_literal!((f64, f64), "Vec2", Vec2, "Vec2");
566
567impl DeferredValue for [f32; 2] {
568 fn eval_deferred(
569 deferred: &Deferred<Self>,
570 node_id: NodeId,
571 property_path: &str,
572 _ctx: &crate::expr::ExpressionContext<'_>,
573 ) -> crate::Result<Self> {
574 match deferred {
575 Deferred::Value(value) => Ok(*value),
576 Deferred::Expr(_) => Err(PropertyValue::invalid_type(
577 node_id,
578 property_path,
579 "Vec2",
580 "expression",
581 )),
582 }
583 }
584
585 fn to_property_value(value: &Self) -> PropertyValue {
586 PropertyValue::Vec2((f64::from(value[0]), f64::from(value[1])))
587 }
588
589 fn from_property_value(value: PropertyValue) -> Option<Self> {
590 match value {
591 PropertyValue::Vec2((x, y)) => Some([x as f32, y as f32]),
592 _ => None,
593 }
594 }
595
596 fn property_kind_name() -> &'static str {
597 "Vec2"
598 }
599}
600
601#[cfg(feature = "json")]
602impl DeferredJsonValue for f64 {
603 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
604 value
605 .as_f64()
606 .or_else(|| value.as_i64().map(|value| value as f64))
607 .ok_or_else(|| "expected float".to_string())
608 }
609}
610
611#[cfg(feature = "json")]
612impl DeferredJsonValue for f32 {
613 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
614 f64::from_json_value(value).map(|value| value as f32)
615 }
616}
617
618#[cfg(feature = "json")]
619impl DeferredJsonValue for i64 {
620 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
621 value
622 .as_i64()
623 .or_else(|| value.as_f64().map(|value| value as i64))
624 .ok_or_else(|| "expected int".to_string())
625 }
626}
627
628#[cfg(feature = "json")]
629impl DeferredJsonValue for u8 {
630 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
631 let value = i64::from_json_value(value)?;
632 u8::try_from(value).map_err(|_| "expected u8".to_string())
633 }
634}
635
636#[cfg(feature = "json")]
637impl DeferredJsonValue for u32 {
638 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
639 let value = i64::from_json_value(value)?;
640 u32::try_from(value).map_err(|_| "expected u32".to_string())
641 }
642}
643
644#[cfg(feature = "json")]
645impl DeferredJsonValue for bool {
646 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
647 value
648 .as_bool()
649 .or_else(|| value.as_i64().map(|value| value != 0))
650 .ok_or_else(|| "expected bool".to_string())
651 }
652}
653
654#[cfg(feature = "json")]
655impl DeferredJsonValue for String {
656 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
657 value
658 .as_str()
659 .map(ToString::to_string)
660 .ok_or_else(|| "expected string".to_string())
661 }
662}
663
664#[cfg(feature = "json")]
665impl DeferredJsonValue for [u8; 4] {
666 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
667 crate::json::parse_color(value).ok_or_else(|| "expected color".to_string())
668 }
669}
670
671#[cfg(feature = "json")]
672impl DeferredJsonValue for vector::paint::Paint {
673 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
674 vector::paint::Paint::from_json_value(value).ok_or_else(|| "expected paint".to_string())
675 }
676}
677
678#[cfg(feature = "json")]
679impl DeferredJsonValue for (f64, f64) {
680 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
681 let values = value
682 .as_array()
683 .ok_or_else(|| "expected vec2".to_string())?;
684 if values.len() != 2 {
685 return Err(format!(
686 "expected vec2, got array of length {}",
687 values.len()
688 ));
689 }
690 let x = values[0]
691 .as_f64()
692 .ok_or_else(|| "expected vec2 x number".to_string())?;
693 let y = values[1]
694 .as_f64()
695 .ok_or_else(|| "expected vec2 y number".to_string())?;
696 Ok((x, y))
697 }
698}
699
700#[cfg(feature = "json")]
701impl DeferredJsonValue for [f32; 2] {
702 fn from_json_value(value: &serde_json::Value) -> Result<Self, String> {
703 let (x, y) = <(f64, f64)>::from_json_value(value)?;
704 Ok([x as f32, y as f32])
705 }
706}