swamp_script_eval/
value_ref.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use std::cell::{Ref, RefCell};
7use std::fmt::{Display, Formatter};
8use std::hash::Hash;
9use std::rc::Rc;
10use swamp_script_core_extra::extra::SparseValueId;
11use swamp_script_core_extra::prelude::{Value, ValueError};
12use swamp_script_core_extra::value::RustType;
13use swamp_script_core_extra::value::ValueRef;
14use tracing::info;
15
16#[derive(Debug, Clone)]
17pub struct ValueReference(pub ValueRef);
18
19impl ValueReference {}
20
21impl ValueReference {
22    #[inline]
23    pub fn set(&self, v: Value) {
24        *self.0.borrow_mut() = v;
25    }
26
27    pub(crate) fn into_iter_mut(self) -> Result<Box<dyn Iterator<Item = ValueRef>>, ValueError> {
28        let mut inner = self.0.borrow_mut();
29        let result = match &mut *inner {
30            Value::Sparse(_rust_type_ref, sparse_map) => {
31                let pairs: Vec<_> = sparse_map.iter_mut().map(|(_k, v)| v.clone()).collect();
32
33                Box::new(pairs.into_iter()) as Box<dyn Iterator<Item = ValueRef>>
34            }
35            Value::Map(_type_ref, seq_map) => {
36                // Clone each Rc<RefCell<Value>> and collect into a Vec
37                let cloned_rc: Vec<ValueRef> = seq_map.values().cloned().collect();
38
39                // Box the iterator from the Vec
40                Box::new(cloned_rc.into_iter()) as Box<dyn Iterator<Item = ValueRef> + 'static>
41            }
42            Value::Vec(_vec_type, values) => {
43                // Clone each Rc<RefCell<Value>> and collect into a Vec
44                let cloned_rc: Vec<ValueRef> = values.iter().cloned().collect();
45
46                // Box the iterator from the Vec
47                Box::new(cloned_rc.into_iter()) as Box<dyn Iterator<Item = ValueRef> + 'static>
48            }
49            _ => {
50                info!(?inner, "not sure what this is:");
51                todo!()
52            }
53        };
54        Ok(result)
55    }
56
57    /// # Errors
58    ///
59    /// # Panics
60    ///
61    pub fn into_iter_mut_pairs(
62        self,
63    ) -> Result<Box<dyn Iterator<Item = (Value, Self)>>, ValueError> {
64        let mut inner = self.0.borrow_mut();
65        let result = match &mut *inner {
66            Value::Sparse(_rust_type_ref, sparse_map) => {
67                let id_type_ref = sparse_map.rust_type_ref_for_id.clone();
68
69                let pairs: Vec<_> = sparse_map
70                    .iter_mut()
71                    .map(|(k, v)| {
72                        (
73                            Value::RustValue(
74                                id_type_ref.clone(),
75                                Rc::new(RefCell::new(Box::new(SparseValueId(k)))),
76                            ),
77                            Self(v.clone()),
78                        )
79                    })
80                    .collect();
81
82                Box::new(pairs.into_iter()) as Box<dyn Iterator<Item = (Value, Self)>>
83            }
84            _ => return Err(ValueError::CanNotCoerceToIterator),
85        };
86        Ok(result)
87    }
88    #[must_use]
89    pub fn downcast_rust_mut<T: RustType + 'static>(&self) -> Option<Rc<RefCell<Box<T>>>> {
90        match &*self.0.borrow() {
91            Value::RustValue(_rust_type_ref, rc) => {
92                let type_matches = {
93                    let guard = rc.borrow();
94                    (**guard).as_any().is::<T>()
95                };
96
97                if type_matches {
98                    Some(unsafe { std::mem::transmute(rc.clone()) })
99                } else {
100                    None
101                }
102            }
103            _ => None,
104        }
105    }
106
107    #[must_use]
108    pub fn unref(&self) -> Ref<Value> {
109        self.0.borrow()
110    }
111
112    #[must_use]
113    pub fn convert_to_string_if_needed(&self) -> String {
114        self.0.borrow().convert_to_string_if_needed()
115    }
116}
117
118impl PartialEq<Self> for ValueReference {
119    fn eq(&self, other: &Self) -> bool {
120        self.0.borrow().eq(&*other.0.borrow())
121    }
122}
123
124impl Eq for ValueReference {}
125
126impl Hash for ValueReference {
127    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
128        self.0.borrow().hash(state);
129    }
130}
131
132impl Display for ValueReference {
133    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134        write!(f, "{}", self.0.borrow())
135    }
136}