Skip to main content

rune/runtime/
tuple.rs

1use core::borrow::Borrow;
2use core::fmt;
3use core::ops::{self, Deref, DerefMut};
4use core::slice;
5
6use crate as rune;
7use crate::alloc::alloc::Global;
8use crate::alloc::borrow::TryToOwned;
9use crate::alloc::clone::TryClone;
10use crate::alloc::fmt::TryWrite;
11use crate::alloc::iter::{IteratorExt, TryFromIteratorIn};
12use crate::alloc::{self, Box};
13use crate::Any;
14
15use super::{
16    ConstValue, ConstValueBuf, Dismantle, EmptyConstContext, Formatter, FromConstValue, FromValue,
17    Handover, Hasher, Mut, ProtocolCaller, RawAnyGuard, Ref, RuntimeError, ToConstValue, ToValue,
18    UnsafeToMut, UnsafeToRef, Value, VmError, VmErrorKind,
19};
20
21/// The type of a tuple slice.
22#[repr(transparent)]
23pub struct Tuple {
24    values: [Value],
25}
26
27impl Tuple {
28    /// Construct a new tuple slice from a reference.
29    pub const fn new(values: &[Value]) -> &Self {
30        // SAFETY: Tuple is repr transparent over [Value].
31        unsafe { &*(values as *const _ as *const Self) }
32    }
33
34    /// Construct a boxed tuple over a boxed slice of values.
35    pub(crate) fn from_boxed(boxed: Box<[Value]>) -> Box<Self> {
36        let (values, Global) = Box::into_raw_with_allocator(boxed);
37        // SAFETY: Tuple is repr transparent over [Value].
38        unsafe { Box::from_raw_in(values as *mut Tuple, Global) }
39    }
40
41    /// Construct a new tuple slice from a mutable reference.
42    pub fn new_mut(values: &mut [Value]) -> &mut Self {
43        // SAFETY: Tuple is repr transparent over [Value].
44        unsafe { &mut *(values as *mut _ as *mut Self) }
45    }
46
47    /// Get the given value at the given index.
48    pub fn get_value<T>(&self, index: usize) -> Result<Option<T>, VmError>
49    where
50        T: FromValue,
51    {
52        let value = match self.values.get(index) {
53            Some(value) => value.clone(),
54            None => return Ok(None),
55        };
56
57        Ok(Some(T::from_value(value)?))
58    }
59
60    pub(crate) fn hash_with(
61        &self,
62        hasher: &mut Hasher,
63        caller: &mut dyn ProtocolCaller,
64    ) -> Result<(), VmError> {
65        for value in self.values.iter() {
66            value.hash_with(hasher, caller)?;
67        }
68
69        Ok(())
70    }
71
72    pub(crate) fn debug_fmt_with(
73        &self,
74        f: &mut Formatter,
75        caller: &mut dyn ProtocolCaller,
76    ) -> Result<(), VmError> {
77        let mut it = self.iter().peekable();
78        write!(f, "(")?;
79
80        while let Some(value) = it.next() {
81            value.debug_fmt_with(f, caller)?;
82
83            if it.peek().is_some() {
84                write!(f, ", ")?;
85            }
86        }
87
88        write!(f, ")")?;
89        Ok(())
90    }
91
92    pub(crate) fn clone_with(
93        &self,
94        caller: &mut dyn ProtocolCaller,
95    ) -> Result<OwnedTuple, VmError> {
96        let mut vec = alloc::Vec::try_with_capacity(self.len())?;
97
98        for value in self.values.iter() {
99            let value = value.clone_with(caller)?;
100            vec.try_push(value)?;
101        }
102
103        Ok(OwnedTuple::try_from(vec)?)
104    }
105}
106
107impl ops::Deref for Tuple {
108    type Target = [Value];
109
110    #[inline]
111    fn deref(&self) -> &Self::Target {
112        &self.values
113    }
114}
115
116impl ops::DerefMut for Tuple {
117    #[inline]
118    fn deref_mut(&mut self) -> &mut Self::Target {
119        &mut self.values
120    }
121}
122
123impl<'a> IntoIterator for &'a Tuple {
124    type Item = &'a Value;
125    type IntoIter = slice::Iter<'a, Value>;
126
127    #[inline]
128    fn into_iter(self) -> Self::IntoIter {
129        self.iter()
130    }
131}
132
133impl<'a> IntoIterator for &'a mut Tuple {
134    type Item = &'a mut Value;
135    type IntoIter = slice::IterMut<'a, Value>;
136
137    #[inline]
138    fn into_iter(self) -> Self::IntoIter {
139        self.iter_mut()
140    }
141}
142
143/// Struct representing a dynamic anonymous object.
144///
145/// To access borrowed values of a tuple in native functions, use [`Tuple`].
146#[derive(Any)]
147#[rune(item = ::std::tuple, name = Tuple, dismantle)]
148#[repr(transparent)]
149pub struct OwnedTuple {
150    inner: Box<[Value]>,
151}
152
153impl OwnedTuple {
154    /// Construct a new empty tuple.
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use rune::runtime::OwnedTuple;
160    ///
161    /// let empty = OwnedTuple::new();
162    /// ```
163    pub fn new() -> Self {
164        Self {
165            inner: Box::default(),
166        }
167    }
168
169    /// Coerce this owned tuple into a boxed tuple.
170    pub fn into_boxed_tuple(self) -> Box<Tuple> {
171        Tuple::from_boxed(self.inner)
172    }
173
174    /// Convert into inner std boxed slice.
175    pub fn into_inner(self) -> Box<[Value]> {
176        self.inner
177    }
178}
179
180/// A tuple is made of the values put into it, and a script can nest one inside
181/// another without any bound, so it hands over what it is made of rather than
182/// being dropped in place.
183impl Dismantle for OwnedTuple {
184    fn dismantle(&mut self, out: &mut Handover<'_>) {
185        out.consume_all(self.iter_mut());
186    }
187}
188
189impl Deref for OwnedTuple {
190    type Target = Tuple;
191
192    #[inline]
193    fn deref(&self) -> &Self::Target {
194        Tuple::new(&self.inner)
195    }
196}
197
198impl DerefMut for OwnedTuple {
199    #[inline]
200    fn deref_mut(&mut self) -> &mut Self::Target {
201        Tuple::new_mut(&mut self.inner)
202    }
203}
204
205impl AsRef<Tuple> for OwnedTuple {
206    #[inline]
207    fn as_ref(&self) -> &Tuple {
208        self
209    }
210}
211
212impl AsMut<Tuple> for OwnedTuple {
213    #[inline]
214    fn as_mut(&mut self) -> &mut Tuple {
215        self
216    }
217}
218
219impl Borrow<Tuple> for OwnedTuple {
220    #[inline]
221    fn borrow(&self) -> &Tuple {
222        self
223    }
224}
225
226impl Default for OwnedTuple {
227    fn default() -> Self {
228        Self::new()
229    }
230}
231
232impl TryClone for OwnedTuple {
233    #[inline]
234    fn try_clone(&self) -> alloc::Result<Self> {
235        Ok(Self {
236            inner: self.inner.try_clone()?,
237        })
238    }
239
240    #[inline]
241    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
242        self.inner.try_clone_from(&source.inner)
243    }
244}
245
246impl fmt::Debug for OwnedTuple {
247    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248        write!(f, "(")?;
249
250        let mut it = self.iter();
251        let last = it.next_back();
252
253        for el in it {
254            write!(f, "{el:?}, ")?;
255        }
256
257        if let Some(last) = last {
258            write!(f, "{last:?}")?;
259        }
260
261        write!(f, ")")?;
262        Ok(())
263    }
264}
265
266impl TryFrom<rust_alloc::vec::Vec<Value>> for OwnedTuple {
267    type Error = alloc::Error;
268
269    #[inline]
270    fn try_from(vec: rust_alloc::vec::Vec<Value>) -> Result<Self, Self::Error> {
271        Ok(Self {
272            inner: alloc::Box::try_from(vec.into_boxed_slice())?,
273        })
274    }
275}
276
277impl TryFrom<alloc::Vec<Value>> for OwnedTuple {
278    type Error = alloc::Error;
279
280    #[inline]
281    fn try_from(vec: alloc::Vec<Value>) -> Result<Self, Self::Error> {
282        Ok(Self {
283            inner: vec.try_into_boxed_slice()?,
284        })
285    }
286}
287
288impl<const N: usize> TryFrom<[Value; N]> for OwnedTuple {
289    type Error = alloc::Error;
290
291    #[inline]
292    fn try_from(values: [Value; N]) -> Result<Self, Self::Error> {
293        Ok(Self {
294            inner: values.try_into()?,
295        })
296    }
297}
298
299impl From<alloc::Box<[Value]>> for OwnedTuple {
300    #[inline]
301    fn from(inner: alloc::Box<[Value]>) -> Self {
302        Self { inner }
303    }
304}
305
306impl TryFrom<alloc::Box<[ConstValueBuf]>> for OwnedTuple {
307    type Error = RuntimeError;
308
309    fn try_from(inner: alloc::Box<[ConstValueBuf]>) -> Result<Self, RuntimeError> {
310        if inner.is_empty() {
311            return Ok(OwnedTuple::new());
312        }
313
314        let mut out = alloc::Vec::try_with_capacity(inner.len())?;
315
316        for value in inner.iter() {
317            out.try_push(value.to_value_with(&EmptyConstContext)?)?;
318        }
319
320        Ok(Self {
321            inner: out.try_into_boxed_slice()?,
322        })
323    }
324}
325
326impl TryFrom<rust_alloc::boxed::Box<[Value]>> for OwnedTuple {
327    type Error = alloc::Error;
328
329    #[inline]
330    fn try_from(inner: rust_alloc::boxed::Box<[Value]>) -> alloc::Result<Self> {
331        Ok(Self {
332            inner: alloc::Box::try_from(inner)?,
333        })
334    }
335}
336
337impl TryFromIteratorIn<Value, Global> for OwnedTuple {
338    #[inline]
339    fn try_from_iter_in<T: IntoIterator<Item = Value>>(
340        iter: T,
341        alloc: Global,
342    ) -> alloc::Result<Self> {
343        Ok(Self {
344            inner: iter.into_iter().try_collect_in(alloc)?,
345        })
346    }
347}
348
349macro_rules! impl_tuple {
350    // Skip conflicting implementation with `()`.
351    (0) => {
352        rune_macros::binding!(#[type_of] impl ::std::tuple::Tuple for ());
353
354        impl FromValue for () {
355            #[inline]
356            fn from_value(value: Value) -> Result<Self, RuntimeError> {
357                value.into_unit()
358            }
359        }
360
361        impl ToValue for () {
362            #[inline]
363            fn to_value(self) -> Result<Value, RuntimeError> {
364                Ok(Value::unit())
365            }
366        }
367    };
368
369    ($count:expr $(, $ty:ident $var:ident $ignore_count:expr)*) => {
370        rune_macros::binding!(#[type_of] impl <$($ty),*> ::std::tuple::Tuple for ($($ty,)*));
371
372        impl <$($ty,)*> FromValue for ($($ty,)*)
373        where
374            $($ty: FromValue,)*
375        {
376            fn from_value(value: Value) -> Result<Self, RuntimeError> {
377                let tuple = value.into_tuple_ref()?;
378
379                let [$($var,)*] = &tuple[..] else {
380                    return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
381                        actual: tuple.len(),
382                        expected: $count,
383                    }));
384                };
385
386                Ok(($(<$ty as FromValue>::from_value($var.clone())?,)*))
387            }
388        }
389
390        impl <$($ty,)*> FromConstValue for ($($ty,)*)
391        where
392            $($ty: FromConstValue,)*
393        {
394            fn from_const_value(value: &ConstValue) -> Result<Self, RuntimeError> {
395                let fields = value.as_tuple()?;
396
397                if fields.len() != $count {
398                    return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
399                        actual: fields.len(),
400                        expected: $count,
401                    }));
402                }
403
404                #[allow(unused_mut, unused_variables)]
405                let mut fields = fields.iter();
406
407                $(
408                    let Some($var) = fields.next() else {
409                        return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
410                            actual: $count,
411                            expected: $count,
412                        }));
413                    };
414                )*
415
416                Ok(($(<$ty as FromConstValue>::from_const_value($var)?,)*))
417            }
418        }
419
420        impl <$($ty,)*> ToValue for ($($ty,)*)
421        where
422            $($ty: ToValue,)*
423        {
424            fn to_value(self) -> Result<Value, RuntimeError> {
425                let ($($var,)*) = self;
426                $(let $var = $var.to_value()?;)*
427                let mut vec = alloc::Vec::try_with_capacity($count)?;
428                $(vec.try_push($var)?;)*
429                let tuple = OwnedTuple::try_from(vec)?;
430                Ok(Value::try_from(tuple)?)
431            }
432        }
433
434        impl <$($ty,)*> ToConstValue for ($($ty,)*)
435        where
436            $($ty: ToConstValue,)*
437        {
438            fn to_const_value(self) -> Result<ConstValueBuf, RuntimeError> {
439                let ($($var,)*) = self;
440                $(let $var = $var.to_const_value()?;)*
441                let mut vec = alloc::Vec::try_with_capacity($count)?;
442                $(vec.try_push($var)?;)*
443                ConstValueBuf::tuple(vec)
444            }
445        }
446    };
447}
448
449repeat_macro!(impl_tuple);
450
451impl FromValue for Box<Tuple> {
452    #[inline]
453    fn from_value(value: Value) -> Result<Self, RuntimeError> {
454        value.into_tuple()
455    }
456}
457
458impl FromValue for Ref<Tuple> {
459    #[inline]
460    fn from_value(value: Value) -> Result<Self, RuntimeError> {
461        value.into_tuple_ref()
462    }
463}
464
465impl FromValue for Mut<Tuple> {
466    #[inline]
467    fn from_value(value: Value) -> Result<Self, RuntimeError> {
468        value.into_tuple_mut()
469    }
470}
471
472impl UnsafeToRef for Tuple {
473    type Guard = RawAnyGuard;
474
475    #[inline]
476    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError> {
477        let value = Ref::from_value(value)?;
478        let (value, guard) = Ref::into_raw(value);
479        Ok((value.as_ref(), guard))
480    }
481}
482
483impl UnsafeToMut for Tuple {
484    type Guard = RawAnyGuard;
485
486    #[inline]
487    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError> {
488        let value = Mut::from_value(value)?;
489        let (mut value, guard) = Mut::into_raw(value);
490        Ok((value.as_mut(), guard))
491    }
492}
493
494impl TryToOwned for Tuple {
495    type Owned = OwnedTuple;
496
497    #[inline]
498    fn try_to_owned(&self) -> alloc::Result<Self::Owned> {
499        let mut vec = alloc::Vec::try_with_capacity(self.len())?;
500
501        for value in self.iter() {
502            vec.try_push(value.clone())?;
503        }
504
505        OwnedTuple::try_from(vec)
506    }
507}