rune/runtime/
dynamic.rs

1use core::borrow::Borrow;
2use core::hash::Hash;
3use core::ops::Deref;
4
5use crate::alloc::{Box, Vec};
6use crate::sync::Arc;
7
8use super::{FromValue, Repr, Rtti, RttiKind, RuntimeError, Tuple, TypeInfo, Value};
9
10/// A reference to a dynamically defined empty type.
11pub struct DynamicEmpty {
12    rtti: Arc<Rtti>,
13}
14
15impl FromValue for DynamicEmpty {
16    #[inline]
17    fn from_value(value: Value) -> Result<Self, RuntimeError> {
18        match value.take_repr() {
19            Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Empty) => Ok(Self {
20                rtti: value.rtti().clone(),
21            }),
22            value => Err(RuntimeError::expected_empty(value.type_info())),
23        }
24    }
25}
26
27impl DynamicEmpty {
28    /// Get human readable type information for the dynamic tuple.
29    #[inline]
30    pub fn type_info(&self) -> TypeInfo {
31        Rtti::type_info(self.rtti.clone())
32    }
33}
34
35/// A reference to a dynamically defined tuple.
36///
37/// This derefs into a [`Tuple`], which can be used to access the individual
38/// fields.
39pub struct DynamicTuple {
40    rtti: Arc<Rtti>,
41    values: Vec<Value>,
42}
43
44impl FromValue for DynamicTuple {
45    #[inline]
46    fn from_value(value: Value) -> Result<Self, RuntimeError> {
47        match value.take_repr() {
48            Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Tuple) => {
49                let mut values = Vec::try_with_capacity(value.len())?;
50
51                for value in value.borrow_ref()?.iter() {
52                    values.try_push(value.clone())?;
53                }
54
55                Ok(Self {
56                    rtti: value.rtti().clone(),
57                    values,
58                })
59            }
60            value => Err(RuntimeError::expected_tuple(value.type_info())),
61        }
62    }
63}
64
65impl DynamicTuple {
66    /// Get human readable type information for the dynamic tuple.
67    #[inline]
68    pub fn type_info(&self) -> TypeInfo {
69        Rtti::type_info(self.rtti.clone())
70    }
71}
72
73impl Deref for DynamicTuple {
74    type Target = Tuple;
75
76    #[inline]
77    fn deref(&self) -> &Self::Target {
78        Tuple::new(&self.values)
79    }
80}
81
82/// A reference to a dynamically defined struct.
83pub struct DynamicStruct {
84    rtti: Arc<Rtti>,
85    values: Vec<Value>,
86}
87
88impl FromValue for DynamicStruct {
89    #[inline]
90    fn from_value(value: Value) -> Result<Self, RuntimeError> {
91        match value.take_repr() {
92            Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Struct) => {
93                let mut values = Vec::try_with_capacity(value.len())?;
94
95                for value in value.borrow_ref()?.iter() {
96                    values.try_push(value.clone())?;
97                }
98
99                Ok(Self {
100                    rtti: value.rtti().clone(),
101                    values,
102                })
103            }
104            value => Err(RuntimeError::expected_struct(value.type_info())),
105        }
106    }
107}
108
109impl DynamicStruct {
110    /// Get a value from the dynamic struct.
111    #[inline]
112    pub fn get<Q>(&self, key: &Q) -> Option<&Value>
113    where
114        Box<str>: Borrow<Q>,
115        Q: Hash + Eq + ?Sized,
116    {
117        let index = *self.rtti.fields.get(key)?;
118        self.values.get(index)
119    }
120
121    /// Get human readable type information for the dynamic struct.
122    #[inline]
123    pub fn type_info(&self) -> TypeInfo {
124        Rtti::type_info(self.rtti.clone())
125    }
126}