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