1use std::borrow::Cow;
2use std::ops::{Deref, DerefMut};
3
4use anathema_state::{Color, Hex, PendingValue, SubTo, Subscriber, Type};
5use anathema_store::smallmap::SmallMap;
6use anathema_templates::Expression;
7
8use crate::attributes::ValueKey;
9use crate::expression::{ValueExpr, ValueResolutionContext, resolve_value};
10use crate::immediate::Resolver;
11use crate::{AttributeStorage, ResolverCtx};
12
13pub type Values<'bp> = SmallMap<ValueKey<'bp>, Value<'bp>>;
14
15pub fn resolve<'bp>(expr: &'bp Expression, ctx: &ResolverCtx<'_, 'bp>, sub: impl Into<Subscriber>) -> Value<'bp> {
16 let resolver = Resolver::new(ctx);
17 let value_expr = resolver.resolve(expr);
18 Value::new(value_expr, sub.into(), ctx.attribute_storage)
19}
20
21pub fn resolve_collection<'bp>(
22 expr: &'bp Expression,
23 ctx: &ResolverCtx<'_, 'bp>,
24 sub: impl Into<Subscriber>,
25) -> Collection<'bp> {
26 let value = resolve(expr, ctx, sub);
27 Collection(value)
28}
29
30#[derive(Debug)]
31pub struct Collection<'bp>(pub(crate) Value<'bp>);
32
33impl<'bp> Collection<'bp> {
34 pub fn reload(&mut self, attributes: &AttributeStorage<'bp>) {
35 self.0.reload(attributes)
36 }
37
38 pub fn len(&self) -> usize {
39 match &self.0.kind {
40 ValueKind::List(vec) => vec.len(),
41 ValueKind::DynList(value) => {
42 let Some(state) = value.as_state() else { return 0 };
43 let Some(list) = state.as_any_list() else { return 0 };
44 list.len()
45 }
46 ValueKind::Int(_)
47 | ValueKind::Float(_)
48 | ValueKind::Bool(_)
49 | ValueKind::Char(_)
50 | ValueKind::Hex(_)
51 | ValueKind::Color(_)
52 | ValueKind::Str(_)
53 | ValueKind::DynMap(_)
54 | ValueKind::Map
55 | ValueKind::Composite(_)
56 | ValueKind::Attributes
57 | ValueKind::Null => 0,
58 }
59 }
60}
61
62#[derive(Debug)]
65pub struct Value<'bp> {
66 pub(crate) expr: ValueExpr<'bp>,
67 pub(crate) sub: Subscriber,
68 pub(crate) kind: ValueKind<'bp>,
69 pub(crate) sub_to: SubTo,
70}
71
72impl<'bp> Value<'bp> {
73 pub fn new(expr: ValueExpr<'bp>, sub: Subscriber, attribute_storage: &AttributeStorage<'bp>) -> Self {
74 let mut sub_to = SubTo::Zero;
75 let mut ctx = ValueResolutionContext::new(attribute_storage, sub, &mut sub_to);
76 let kind = resolve_value(&expr, &mut ctx);
77
78 match kind {
88 ValueKind::DynMap(pending) | ValueKind::Composite(pending) => {
89 pending.subscribe(ctx.sub);
90 ctx.sub_to.push(pending.sub_key());
91 }
92 _ => {}
93 }
94 Self {
95 expr,
96 sub,
97 kind,
98 sub_to,
99 }
100 }
101
102 pub fn truthiness(&self) -> bool {
103 self.kind.truthiness()
113 }
114
115 #[doc(hidden)]
116 pub fn kind(&self) -> &ValueKind<'_> {
117 &self.kind
118 }
119
120 pub fn reload(&mut self, attribute_storage: &AttributeStorage<'bp>) {
121 self.sub_to.unsubscribe(self.sub);
122 let mut ctx = ValueResolutionContext::new(attribute_storage, self.sub, &mut self.sub_to);
123 self.kind = resolve_value(&self.expr, &mut ctx);
124 }
125
126 pub fn try_as<T>(&self) -> Option<T>
127 where
128 T: for<'a> TryFrom<&'a ValueKind<'a>>,
129 {
130 (&self.kind).try_into().ok()
131 }
132
133 pub fn strings<F>(&self, mut f: F)
134 where
135 F: FnMut(&str) -> bool,
136 {
137 self.kind.strings(&mut f);
138 }
139}
140
141impl Drop for Value<'_> {
142 fn drop(&mut self) {
143 self.sub_to.unsubscribe(self.sub);
144 }
145}
146
147impl<'a> Deref for Value<'a> {
148 type Target = ValueKind<'a>;
149
150 fn deref(&self) -> &Self::Target {
151 &self.kind
152 }
153}
154
155impl<'a> DerefMut for Value<'a> {
156 fn deref_mut(&mut self) -> &mut Self::Target {
157 &mut self.kind
158 }
159}
160
161#[derive(Debug, PartialEq, PartialOrd, Clone)]
165pub enum ValueKind<'bp> {
166 Int(i64),
167 Float(f64),
168 Bool(bool),
169 Char(char),
170 Hex(Hex),
171 Color(Color),
172 Str(Cow<'bp, str>),
173 Null,
174
175 Map,
179 Attributes,
183 List(Box<[ValueKind<'bp>]>),
184 DynList(PendingValue),
185 DynMap(PendingValue),
186 Composite(PendingValue),
187}
188
189impl ValueKind<'_> {
190 pub fn to_int(&self) -> Option<i64> {
191 match self.as_int() {
192 Some(val) => Some(val),
193 None => Some(self.as_float()? as i64),
194 }
195 }
196
197 pub fn as_int(&self) -> Option<i64> {
198 let ValueKind::Int(i) = self else { return None };
199 Some(*i)
200 }
201
202 pub fn as_float(&self) -> Option<f64> {
203 let ValueKind::Float(i) = self else { return None };
204 Some(*i)
205 }
206
207 pub fn as_bool(&self) -> Option<bool> {
208 let ValueKind::Bool(b) = self else { return None };
209 Some(*b)
210 }
211
212 pub fn as_char(&self) -> Option<char> {
213 let ValueKind::Char(i) = self else { return None };
214 Some(*i)
215 }
216
217 pub fn as_hex(&self) -> Option<Hex> {
218 let ValueKind::Hex(i) = self else { return None };
219 Some(*i)
220 }
221
222 pub fn as_color(&self) -> Option<Color> {
223 let ValueKind::Color(i) = self else { return None };
224 Some(*i)
225 }
226
227 pub fn as_str(&self) -> Option<&str> {
228 let ValueKind::Str(i) = &self else { return None };
229 Some(i)
230 }
231
232 pub fn strings<F>(&self, mut f: F)
233 where
234 F: FnMut(&str) -> bool,
235 {
236 self.internal_strings(&mut f);
237 }
238
239 fn internal_strings<F>(&self, f: &mut F) -> bool
240 where
241 F: FnMut(&str) -> bool,
242 {
243 match self {
244 ValueKind::Int(n) => f(&n.to_string()),
245 ValueKind::Float(n) => f(&n.to_string()),
246 ValueKind::Bool(b) => f(&b.to_string()),
247 ValueKind::Char(c) => f(&c.to_string()),
248 ValueKind::Hex(x) => f(&x.to_string()),
249 ValueKind::Color(col) => f(&col.to_string()),
250 ValueKind::Str(cow) => f(cow.as_ref()),
251 ValueKind::List(vec) => vec.iter().take_while(|val| val.internal_strings(f)).count() == vec.len(),
252 ValueKind::DynList(value) => dyn_string(*value, f),
253 ValueKind::DynMap(_) => f("<dyn map>"),
254 ValueKind::Map => f("<map>"),
255 ValueKind::Composite(_) => f("<composite>"),
256 ValueKind::Attributes => f("<attributes>"),
257 ValueKind::Null => true,
258 }
259 }
260
261 pub(crate) fn truthiness(&self) -> bool {
262 match self {
263 ValueKind::Int(0) | ValueKind::Float(0.0) | ValueKind::Bool(false) => false,
264 ValueKind::Str(cow) if cow.is_empty() => false,
265 ValueKind::Null => false,
266 ValueKind::List(list) if list.is_empty() => false,
267 ValueKind::DynList(list) => {
268 let Some(state) = list.as_state() else { return false };
269 let Some(state) = state.as_any_list() else { return false };
270 !state.is_empty()
271 }
272 ValueKind::DynMap(map) => {
273 let Some(state) = map.as_state() else { return false };
274 let Some(state) = state.as_any_map() else { return false };
275 !state.is_empty()
276 }
277 _ => true,
279 }
280 }
281}
282
283fn dyn_string<F>(value: PendingValue, f: &mut F) -> bool
284where
285 F: FnMut(&str) -> bool,
286{
287 let Some(state) = value.as_state() else { return true };
288 let Some(list) = state.as_any_list() else { return true };
289 for i in 0..list.len() {
290 let value = list.lookup(i).expect("the value exists");
291 let Some(state) = value.as_state() else { continue };
292 let should_continue = match value.type_info() {
293 Type::Int => f(&state.as_int().expect("type info dictates this").to_string()),
294 Type::Float => f(&state.as_float().expect("type info dictates this").to_string()),
295 Type::Char => f(&state.as_char().expect("type info dictates this").to_string()),
296 Type::String => f(state.as_str().expect("type info dictates this")),
297 Type::Bool => f(&state.as_bool().expect("type info dictates this").to_string()),
298 Type::Hex => f(&state.as_hex().expect("type info dictates this").to_string()),
299 Type::Map => f("<map>"),
300 Type::List => dyn_string(value, f),
301 Type::Composite => f(&state.as_hex().expect("type info dictates this").to_string()),
302 Type::Unit => f(""),
303 Type::Color => f(&state.as_color().expect("type info dictates this").to_string()),
304 Type::Maybe => panic!(),
305 };
306
307 if !should_continue {
308 return false;
309 }
310 }
311 true
312}
313
314macro_rules! from_int {
318 ($int:ty) => {
319 impl From<$int> for ValueKind<'_> {
320 fn from(value: $int) -> Self {
321 ValueKind::Int(value as i64)
322 }
323 }
324 };
325}
326
327from_int!(i64);
328from_int!(i32);
329from_int!(i16);
330from_int!(i8);
331from_int!(u64);
332from_int!(u32);
333from_int!(u16);
334from_int!(u8);
335
336impl From<f64> for ValueKind<'_> {
337 fn from(value: f64) -> Self {
338 ValueKind::Float(value)
339 }
340}
341
342impl From<f32> for ValueKind<'_> {
343 fn from(value: f32) -> Self {
344 ValueKind::Float(value as f64)
345 }
346}
347
348impl From<bool> for ValueKind<'_> {
349 fn from(value: bool) -> Self {
350 ValueKind::Bool(value)
351 }
352}
353
354impl From<char> for ValueKind<'_> {
355 fn from(value: char) -> Self {
356 ValueKind::Char(value)
357 }
358}
359
360impl From<Hex> for ValueKind<'_> {
361 fn from(value: Hex) -> Self {
362 ValueKind::Hex(value)
363 }
364}
365
366impl From<Color> for ValueKind<'_> {
367 fn from(value: Color) -> Self {
368 ValueKind::Color(value)
369 }
370}
371
372impl<'bp, T> From<Vec<T>> for ValueKind<'bp>
373where
374 T: Into<ValueKind<'bp>>,
375{
376 fn from(value: Vec<T>) -> Self {
377 let list = value.into_iter().map(T::into).collect();
378 ValueKind::List(list)
379 }
380}
381
382impl<'a> From<&'a str> for ValueKind<'a> {
383 fn from(value: &'a str) -> Self {
384 ValueKind::Str(Cow::Borrowed(value))
385 }
386}
387
388impl From<String> for ValueKind<'_> {
389 fn from(value: String) -> Self {
390 ValueKind::Str(value.into())
391 }
392}
393
394macro_rules! try_from_valuekind {
398 ($t:ty, $kind:ident) => {
399 impl TryFrom<&ValueKind<'_>> for $t {
400 type Error = ();
401
402 fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
403 match value {
404 ValueKind::$kind(val) => Ok(*val),
405 _ => Err(()),
406 }
407 }
408 }
409 };
410}
411
412macro_rules! try_from_valuekind_int {
413 ($t:ty, $kind:ident) => {
414 impl TryFrom<&ValueKind<'_>> for $t {
415 type Error = ();
416
417 fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
418 match value {
419 ValueKind::$kind(val) => Ok(*val as $t),
420 _ => Err(()),
421 }
422 }
423 }
424 };
425}
426
427try_from_valuekind!(i64, Int);
428try_from_valuekind!(f64, Float);
429try_from_valuekind!(bool, Bool);
430try_from_valuekind!(Hex, Hex);
431try_from_valuekind!(Color, Color);
432
433try_from_valuekind_int!(usize, Int);
434try_from_valuekind_int!(isize, Int);
435try_from_valuekind_int!(i32, Int);
436try_from_valuekind_int!(f32, Float);
437try_from_valuekind_int!(i16, Int);
438try_from_valuekind_int!(i8, Int);
439try_from_valuekind_int!(u32, Int);
440try_from_valuekind_int!(u64, Int);
441try_from_valuekind_int!(u16, Int);
442try_from_valuekind_int!(u8, Int);
443
444impl<'bp> TryFrom<&ValueKind<'bp>> for char {
445 type Error = ();
446
447 fn try_from(value: &ValueKind<'bp>) -> Result<Self, Self::Error> {
448 match value {
449 ValueKind::Char(c) => Ok(*c),
450 ValueKind::Str(s) => s.chars().next().ok_or(()),
451 _ => Err(()),
452 }
453 }
454}
455
456impl<'a, 'bp> TryFrom<&'a ValueKind<'bp>> for &'a str {
457 type Error = ();
458
459 fn try_from(value: &'a ValueKind<'bp>) -> Result<Self, Self::Error> {
460 match value {
461 ValueKind::Str(Cow::Borrowed(val)) => Ok(val),
462 ValueKind::Str(Cow::Owned(val)) => Ok(val.as_str()),
463 _ => Err(()),
464 }
465 }
466}
467
468#[cfg(test)]
469pub(crate) mod test {
470 use anathema_state::{Hex, Map, Maybe, States};
471 use anathema_templates::Variables;
472 use anathema_templates::expressions::{
473 add, and, boolean, chr, div, either, eq, float, greater_than, greater_than_equal, hex, ident, index, less_than,
474 less_than_equal, list, map, modulo, mul, neg, not, num, or, strlit, sub, text_segments,
475 };
476
477 use crate::ValueKind;
478 use crate::testing::setup;
479
480 #[test]
481 fn attribute_lookup() {
482 let expr = index(ident("attributes"), strlit("a"));
483 let int = num(123);
484
485 let mut states = States::new();
486 setup(&mut states, Default::default(), |test| {
487 test.set_attribute("a", &int);
488 let value = test.eval(&expr);
489 assert_eq!(123, value.as_int().unwrap());
490 });
491 }
492
493 #[test]
494 fn expr_list_dyn_index() {
495 let expr = index(list([1, 2, 3]), add(ident("index"), num(1)));
496
497 let mut states = States::new();
498 let mut globals = Variables::new();
499 globals.declare("index", 0);
500
501 setup(&mut states, globals, |test| {
502 let value = test.eval(&expr);
503 assert_eq!(2, value.as_int().unwrap());
504 });
505 }
506
507 #[test]
508 fn expr_list() {
509 let expr = index(list([1, 2, 3]), num(0));
510
511 let mut states = States::new();
512 setup(&mut states, Default::default(), |test| {
513 let value = test.eval(&expr);
514 assert_eq!(1, value.as_int().unwrap());
515 });
516 }
517
518 #[test]
519 fn either_index() {
520 let expr = either(
522 index(index(ident("state"), strlit("list")), num(0)),
523 index(index(ident("attributes"), strlit("list")), num(0)),
524 );
525
526 let list = list([strlit("from attribute")]);
527
528 let mut states = States::new();
529 setup(&mut states, Default::default(), |test| {
530 test.set_attribute("list", &list);
532
533 let mut value = test.eval(&expr);
536 assert_eq!("from attribute", value.as_str().unwrap());
537
538 test.with_state(|state| state.list.push("from state"));
540
541 value.reload(&test.attributes);
543 assert_eq!("from state", value.as_str().unwrap());
544 });
545 }
546
547 #[test]
548 fn either_then_index() {
549 let list = list([num(123)]);
552 let mut states = States::new();
553 setup(&mut states, Default::default(), |test| {
554 let expr = index(
555 either(
556 index(ident("attributes"), strlit("list")),
557 index(ident("state"), strlit("list")),
558 ),
559 num(0),
560 );
561
562 test.with_state(|state| state.list.push("a string"));
563 let value = test.eval(&expr);
564 assert_eq!("a string", value.as_str().unwrap());
565
566 test.set_attribute("list", &list);
567 let value = test.eval(&expr);
568 assert_eq!(123, value.as_int().unwrap());
569 });
570 }
571
572 #[test]
573 fn either_or() {
574 let mut states = States::new();
575 setup(&mut states, Default::default(), |test| {
576 test.with_state(|state| state.num.set(1));
577 test.with_state(|state| state.num_2.set(2));
578
579 let expr = either(
581 index(ident("state"), strlit("num_3")),
582 index(ident("state"), strlit("num_2")),
583 );
584 let value = test.eval(&expr);
585 assert_eq!(2, value.as_int().unwrap());
586
587 let expr = either(
589 index(ident("state"), strlit("num")),
590 index(ident("state"), strlit("num_2")),
591 );
592 let value = test.eval(&expr);
593 assert_eq!(1, value.as_int().unwrap());
594 });
595 }
596
597 #[test]
598 fn mods() {
599 let mut states = States::new();
600 setup(&mut states, Default::default(), |test| {
601 test.with_state(|state| state.num.set(5));
602 let lookup = index(ident("state"), strlit("num"));
603 let expr = modulo(lookup, num(3));
604 let value = test.eval(&expr);
605 assert_eq!(2, value.as_int().unwrap());
606 });
607 }
608
609 #[test]
610 fn division() {
611 let mut states = States::new();
612 setup(&mut states, Default::default(), |test| {
613 test.with_state(|state| state.num.set(6));
614 let lookup = index(ident("state"), strlit("num"));
615 let expr = div(lookup, num(2));
616 let value = test.eval(&expr);
617 assert_eq!(3, value.as_int().unwrap());
618 });
619 }
620
621 #[test]
622 fn multiplication() {
623 let mut states = States::new();
624 setup(&mut states, Default::default(), |test| {
625 test.with_state(|state| state.num.set(2));
626 let lookup = index(ident("state"), strlit("num"));
627 let expr = mul(lookup, num(2));
628 let value = test.eval(&expr);
629 assert_eq!(4, value.as_int().unwrap());
630 });
631 }
632
633 #[test]
634 fn subtraction() {
635 let mut states = States::new();
636 setup(&mut states, Default::default(), |test| {
637 test.with_state(|state| state.num.set(1));
638 let lookup = index(ident("state"), strlit("num"));
639 let expr = sub(lookup, num(2));
640 let value = test.eval(&expr);
641 assert_eq!(-1, value.as_int().unwrap());
642 });
643 }
644
645 #[test]
646 fn addition() {
647 let mut states = States::new();
648 setup(&mut states, Default::default(), |test| {
649 test.with_state(|state| state.num.set(1));
650 let lookup = index(ident("state"), strlit("num"));
651 let expr = add(lookup, num(2));
652 let value = test.eval(&expr);
653 assert_eq!(3, value.as_int().unwrap());
654 });
655 }
656
657 #[test]
658 fn test_or() {
659 let mut states = States::new();
660 setup(&mut states, Default::default(), |test| {
661 let is_true = or(boolean(false), boolean(true));
662 let is_true = test.eval(&is_true);
663 assert!(is_true.as_bool().unwrap());
664 });
665 }
666
667 #[test]
668 fn test_and() {
669 let mut states = States::new();
670 setup(&mut states, Default::default(), |test| {
671 let is_true = and(boolean(true), boolean(true));
672 let is_true = test.eval(&is_true);
673 assert!(is_true.as_bool().unwrap());
674 });
675 }
676
677 #[test]
678 fn lte() {
679 let mut states = States::new();
680 setup(&mut states, Default::default(), |test| {
681 let is_true = less_than_equal(num(1), num(2));
682 let is_also_true = less_than_equal(num(1), num(1));
683 let is_true = test.eval(&is_true);
684 let is_also_true = test.eval(&is_also_true);
685 assert!(is_true.as_bool().unwrap());
686 assert!(is_also_true.as_bool().unwrap());
687 });
688 }
689
690 #[test]
691 fn lt() {
692 let mut states = States::new();
693 setup(&mut states, Default::default(), |test| {
694 let is_true = less_than(num(1), num(2));
695 let is_false = less_than(num(1), num(1));
696 let is_true = test.eval(&is_true);
697 let is_false = test.eval(&is_false);
698 assert!(is_true.as_bool().unwrap());
699 assert!(!is_false.as_bool().unwrap());
700 });
701 }
702
703 #[test]
704 fn gte() {
705 let mut states = States::new();
706 setup(&mut states, Default::default(), |test| {
707 let is_true = greater_than_equal(num(2), num(1));
708 let is_also_true = greater_than_equal(num(2), num(2));
709 let is_true = test.eval(&is_true);
710 let is_also_true = test.eval(&is_also_true);
711 assert!(is_true.as_bool().unwrap());
712 assert!(is_also_true.as_bool().unwrap());
713 });
714 }
715
716 #[test]
717 fn gt() {
718 let mut states = States::new();
719 setup(&mut states, Default::default(), |test| {
720 let is_true = greater_than(num(2), num(1));
721 let is_false = greater_than(num(2), num(2));
722 let is_true = test.eval(&is_true);
723 let is_false = test.eval(&is_false);
724 assert!(is_true.as_bool().unwrap());
725 assert!(!is_false.as_bool().unwrap());
726 });
727 }
728
729 #[test]
730 fn equality() {
731 let mut states = States::new();
732 setup(&mut states, Default::default(), |test| {
733 let is_true = eq(num(1), num(1));
734 let is_true = test.eval(&is_true);
735 let is_false = ¬(eq(num(1), num(1)));
736 let is_false = test.eval(is_false);
737 assert!(is_true.as_bool().unwrap());
738 assert!(!is_false.as_bool().unwrap());
739 });
740 }
741
742 #[test]
743 fn neg_float() {
744 let mut states = States::new();
745 setup(&mut states, Default::default(), |test| {
746 let expr = neg(float(123.1));
747 let value = test.eval(&expr);
748 assert_eq!(-123.1, value.as_float().unwrap());
749 });
750 }
751
752 #[test]
753 fn neg_num() {
754 let mut states = States::new();
755 setup(&mut states, Default::default(), |test| {
756 let expr = neg(num(123));
757 let value = test.eval(&expr);
758 assert_eq!(-123, value.as_int().unwrap());
759 });
760 }
761
762 #[test]
763 fn not_true() {
764 let mut states = States::new();
765 setup(&mut states, Default::default(), |test| {
766 let expr = not(boolean(false));
767 let value = test.eval(&expr);
768 assert!(value.as_bool().unwrap());
769 });
770 }
771
772 #[test]
773 fn map_resolve() {
774 let mut states = States::new();
775 setup(&mut states, Default::default(), |test| {
776 let expr = map([("a", 123), ("b", 456)]);
777 let value = test.eval(&expr);
778 assert_eq!(ValueKind::Map, value.kind);
779 });
780 }
781
782 #[test]
783 fn optional_map_resolve() {
784 let mut states = States::new();
785 setup(&mut states, Default::default(), |test| {
786 let expr = index(ident("state"), strlit("opt_map"));
788 let mut value = test.eval(&expr);
789 assert!(matches!(value.kind, ValueKind::Null));
790
791 test.with_state(|state| {
793 let map = Map::empty();
794 state.opt_map.set(Maybe::some(map));
795 });
796
797 value.reload(&test.attributes);
798 assert!(matches!(value.kind, ValueKind::DynMap(_)));
799 });
800 }
801
802 #[test]
803 fn str_resolve() {
804 let mut states = States::new();
806 let mut globals = Variables::new();
807 globals.declare("full", "string");
808 setup(&mut states, globals, |test| {
809 let expr = index(ident("state"), either(ident("empty"), ident("full")));
810 test.with_state(|state| state.string.set("a string"));
811 let value = test.eval(&expr);
812 assert_eq!("a string", value.as_str().unwrap());
813 });
814 }
815
816 #[test]
817 fn state_string() {
818 let mut states = States::new();
819 setup(&mut states, Default::default(), |test| {
820 test.with_state(|state| state.string.set("a string"));
821 let expr = index(ident("state"), strlit("string"));
822 let value = test.eval(&expr);
823 assert_eq!("a string", value.as_str().unwrap());
824 });
825 }
826
827 #[test]
828 fn state_float() {
829 let mut states = States::new();
830 setup(&mut states, Default::default(), |test| {
831 let expr = index(ident("state"), strlit("float"));
832 test.with_state(|state| state.float.set(1.2));
833 let value = test.eval(&expr);
834 assert_eq!(1.2, value.as_float().unwrap());
835 });
836 }
837
838 #[test]
839 fn test_either() {
840 let mut states = States::new();
841 let mut globals = Variables::new();
842 globals.declare("missing", 111);
843 setup(&mut states, globals, |test| {
844 let expr = either(ident("missings"), num(2));
845 let value = test.eval(&expr);
846 assert_eq!(2, value.as_int().unwrap());
847 });
848 }
849
850 #[test]
851 fn test_hex() {
852 let mut states = States::new();
853 setup(&mut states, Default::default(), |test| {
854 let expr = hex((1, 2, 3));
855 let value = test.eval(&expr);
856 assert_eq!(Hex::from((1, 2, 3)), value.as_hex().unwrap());
857 });
858 }
859
860 #[test]
861 fn test_char() {
862 let mut states = States::new();
863 setup(&mut states, Default::default(), |test| {
864 let expr = chr('x');
865 let value = test.eval(&expr);
866 assert_eq!('x', value.as_char().unwrap());
867 });
868 }
869
870 #[test]
871 fn test_float() {
872 let mut states = States::new();
873 setup(&mut states, Default::default(), |test| {
874 let expr = float(123.123);
875 let value = test.eval(&expr);
876 assert_eq!(123.123, value.as_float().unwrap());
877 });
878 }
879
880 #[test]
881 fn test_int() {
882 let mut states = States::new();
883 setup(&mut states, Default::default(), |test| {
884 let expr = num(123);
885 let value = test.eval(&expr);
886 assert_eq!(123, value.as_int().unwrap());
887 });
888 }
889
890 #[test]
891 fn test_bool() {
892 let mut states = States::new();
893 setup(&mut states, Default::default(), |test| {
894 let expr = boolean(true);
895 let value = test.eval(&expr);
896 assert!(value.as_bool().unwrap());
897 });
898 }
899
900 #[test]
901 fn test_dyn_list() {
902 let mut states = States::new();
903 setup(&mut states, Default::default(), |test| {
904 test.with_state(|state| {
905 state.list.push("abc");
906 state.list.push("def");
907 });
908 let expr = index(index(ident("state"), strlit("list")), num(1));
909 let value = test.eval(&expr);
910 assert_eq!("def", value.as_str().unwrap());
911 });
912 }
913
914 #[test]
915 fn test_expression_map_state_key() {
916 let mut states = States::new();
917 setup(&mut states, Default::default(), |test| {
918 let expr = index(map([("value", 123)]), index(ident("state"), strlit("string")));
919 test.with_state(|state| state.string.set("value"));
920 let value = test.eval(&expr);
921 assert_eq!(123, value.as_int().unwrap());
922 });
923 }
924
925 #[test]
926 fn test_expression_map() {
927 let mut states = States::new();
928 setup(&mut states, Default::default(), |test| {
929 let expr = index(map([("value", 123)]), strlit("value"));
930 let value = test.eval(&expr);
931 assert_eq!(123, value.as_int().unwrap());
932 });
933 }
934
935 #[test]
936 fn test_state_lookup() {
937 let mut states = States::new();
938 setup(&mut states, Default::default(), |test| {
939 let expr = index(ident("state"), strlit("num"));
940 let value = test.eval(&expr);
941 assert_eq!(0, value.as_int().unwrap());
942 });
943 }
944
945 #[test]
946 fn test_nested_map() {
947 let mut states = States::new();
948 setup(&mut states, Default::default(), |test| {
949 let expr = index(index(ident("state"), strlit("map")), strlit("value"));
950 test.with_state(|state| state.map.to_mut().insert("value", 123));
951 let value = test.eval(&expr);
952 assert_eq!(123, value.as_int().unwrap());
953 });
954 }
955
956 #[test]
976 fn stringify() {
977 let mut states = States::new();
978 setup(&mut states, Default::default(), |test| {
979 let expr = text_segments([strlit("hello"), strlit(" "), strlit("world")]);
980 let value = test.eval(&expr);
981 let mut actual = String::new();
982 value.strings(|st| {
983 actual.push_str(st);
984 true
985 });
986 assert_eq!("hello world", &actual);
987 });
988 }
989}