Skip to main content

ferroui_base/utilities/
boolean_boxes.rs

1//! Cached boxes of the two boolean values: reading a boolean into an
2//! untyped value does not allocate a new box per read.
3
4use crate::BoxedValue;
5use std::rc::Rc;
6
7crate::ferro_thread_local! {
8    static TRUE: BoxedValue = Rc::new(true);
9    static FALSE: BoxedValue = Rc::new(false);
10}
11
12/// The cached boxes of `true` and `false`.
13pub struct BooleanBoxes;
14
15impl BooleanBoxes {
16    /// The box of `true` (one per thread).
17    pub fn true_() -> BoxedValue {
18        TRUE.with(Clone::clone)
19    }
20
21    /// The box of `false` (one per thread).
22    pub fn false_() -> BoxedValue {
23        FALSE.with(Clone::clone)
24    }
25
26    /// The cached box of `value`.
27    pub fn box_(value: bool) -> BoxedValue {
28        if value {
29            Self::true_()
30        } else {
31            Self::false_()
32        }
33    }
34
35    /// Boxes `value`: a boolean as its cached box, any other value as a new
36    /// box.
37    pub fn box_value<T: PartialEq + Clone + 'static>(value: &T) -> BoxedValue {
38        let any: &dyn std::any::Any = value;
39        match any.downcast_ref::<bool>() {
40            Some(value) => Self::box_(*value),
41            None => Rc::new(value.clone()),
42        }
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn booleans_share_their_boxes() {
52        assert!(Rc::ptr_eq(&BooleanBoxes::box_(true), &BooleanBoxes::true_()));
53        assert!(Rc::ptr_eq(&BooleanBoxes::box_(false), &BooleanBoxes::false_()));
54        assert!(!Rc::ptr_eq(&BooleanBoxes::box_(true), &BooleanBoxes::box_(false)));
55        assert_eq!(BooleanBoxes::box_(true).downcast_ref::<bool>(), Some(&true));
56        assert_eq!(BooleanBoxes::box_(false).downcast_ref::<bool>(), Some(&false));
57        assert!(Rc::ptr_eq(&BooleanBoxes::box_value(&true), &BooleanBoxes::box_value(&true)));
58        let (a, b) = (BooleanBoxes::box_value(&1i32), BooleanBoxes::box_value(&1i32));
59        assert!(!Rc::ptr_eq(&a, &b));
60        assert_eq!(a.downcast_ref::<i32>(), Some(&1));
61    }
62}