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, EmptyConstContext, Formatter, FromConstValue, FromValue, Hasher, Mut,
17    ProtocolCaller, RawAnyGuard, Ref, RuntimeError, ToConstValue, ToValue, UnsafeToMut,
18    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)]
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
180impl Deref for OwnedTuple {
181    type Target = Tuple;
182
183    #[inline]
184    fn deref(&self) -> &Self::Target {
185        Tuple::new(&self.inner)
186    }
187}
188
189impl DerefMut for OwnedTuple {
190    #[inline]
191    fn deref_mut(&mut self) -> &mut Self::Target {
192        Tuple::new_mut(&mut self.inner)
193    }
194}
195
196impl AsRef<Tuple> for OwnedTuple {
197    #[inline]
198    fn as_ref(&self) -> &Tuple {
199        self
200    }
201}
202
203impl AsMut<Tuple> for OwnedTuple {
204    #[inline]
205    fn as_mut(&mut self) -> &mut Tuple {
206        self
207    }
208}
209
210impl Borrow<Tuple> for OwnedTuple {
211    #[inline]
212    fn borrow(&self) -> &Tuple {
213        self
214    }
215}
216
217impl Default for OwnedTuple {
218    fn default() -> Self {
219        Self::new()
220    }
221}
222
223impl TryClone for OwnedTuple {
224    #[inline]
225    fn try_clone(&self) -> alloc::Result<Self> {
226        Ok(Self {
227            inner: self.inner.try_clone()?,
228        })
229    }
230
231    #[inline]
232    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
233        self.inner.try_clone_from(&source.inner)
234    }
235}
236
237impl fmt::Debug for OwnedTuple {
238    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239        write!(f, "(")?;
240
241        let mut it = self.iter();
242        let last = it.next_back();
243
244        for el in it {
245            write!(f, "{el:?}, ")?;
246        }
247
248        if let Some(last) = last {
249            write!(f, "{last:?}")?;
250        }
251
252        write!(f, ")")?;
253        Ok(())
254    }
255}
256
257impl TryFrom<rust_alloc::vec::Vec<Value>> for OwnedTuple {
258    type Error = alloc::Error;
259
260    #[inline]
261    fn try_from(vec: rust_alloc::vec::Vec<Value>) -> Result<Self, Self::Error> {
262        Ok(Self {
263            inner: alloc::Box::try_from(vec.into_boxed_slice())?,
264        })
265    }
266}
267
268impl TryFrom<alloc::Vec<Value>> for OwnedTuple {
269    type Error = alloc::Error;
270
271    #[inline]
272    fn try_from(vec: alloc::Vec<Value>) -> Result<Self, Self::Error> {
273        Ok(Self {
274            inner: vec.try_into_boxed_slice()?,
275        })
276    }
277}
278
279impl<const N: usize> TryFrom<[Value; N]> for OwnedTuple {
280    type Error = alloc::Error;
281
282    #[inline]
283    fn try_from(values: [Value; N]) -> Result<Self, Self::Error> {
284        Ok(Self {
285            inner: values.try_into()?,
286        })
287    }
288}
289
290impl From<alloc::Box<[Value]>> for OwnedTuple {
291    #[inline]
292    fn from(inner: alloc::Box<[Value]>) -> Self {
293        Self { inner }
294    }
295}
296
297impl TryFrom<alloc::Box<[ConstValue]>> for OwnedTuple {
298    type Error = RuntimeError;
299
300    fn try_from(inner: alloc::Box<[ConstValue]>) -> Result<Self, RuntimeError> {
301        if inner.is_empty() {
302            return Ok(OwnedTuple::new());
303        }
304
305        let mut out = alloc::Vec::try_with_capacity(inner.len())?;
306
307        for value in inner.iter() {
308            out.try_push(value.to_value_with(&EmptyConstContext)?)?;
309        }
310
311        Ok(Self {
312            inner: out.try_into_boxed_slice()?,
313        })
314    }
315}
316
317impl TryFrom<rust_alloc::boxed::Box<[Value]>> for OwnedTuple {
318    type Error = alloc::Error;
319
320    #[inline]
321    fn try_from(inner: rust_alloc::boxed::Box<[Value]>) -> alloc::Result<Self> {
322        Ok(Self {
323            inner: alloc::Box::try_from(inner)?,
324        })
325    }
326}
327
328impl TryFrom<rust_alloc::boxed::Box<[ConstValue]>> for OwnedTuple {
329    type Error = RuntimeError;
330
331    #[inline]
332    fn try_from(inner: rust_alloc::boxed::Box<[ConstValue]>) -> Result<Self, RuntimeError> {
333        if inner.is_empty() {
334            return Ok(OwnedTuple::new());
335        }
336
337        let mut out = alloc::Vec::try_with_capacity(inner.len())?;
338
339        for value in inner.iter() {
340            out.try_push(value.to_value_with(&EmptyConstContext)?)?;
341        }
342
343        Ok(Self {
344            inner: out.try_into_boxed_slice()?,
345        })
346    }
347}
348
349impl TryFromIteratorIn<Value, Global> for OwnedTuple {
350    #[inline]
351    fn try_from_iter_in<T: IntoIterator<Item = Value>>(
352        iter: T,
353        alloc: Global,
354    ) -> alloc::Result<Self> {
355        Ok(Self {
356            inner: iter.into_iter().try_collect_in(alloc)?,
357        })
358    }
359}
360
361macro_rules! impl_tuple {
362    // Skip conflicting implementation with `()`.
363    (0) => {
364        rune_macros::binding!(#[type_of] impl ::std::tuple::Tuple for ());
365
366        impl FromValue for () {
367            #[inline]
368            fn from_value(value: Value) -> Result<Self, RuntimeError> {
369                value.into_unit()
370            }
371        }
372
373        impl ToValue for () {
374            #[inline]
375            fn to_value(self) -> Result<Value, RuntimeError> {
376                Ok(Value::unit())
377            }
378        }
379    };
380
381    ($count:expr $(, $ty:ident $var:ident $ignore_count:expr)*) => {
382        rune_macros::binding!(#[type_of] impl <$($ty),*> ::std::tuple::Tuple for ($($ty,)*));
383
384        impl <$($ty,)*> FromValue for ($($ty,)*)
385        where
386            $($ty: FromValue,)*
387        {
388            fn from_value(value: Value) -> Result<Self, RuntimeError> {
389                let tuple = value.into_tuple_ref()?;
390
391                let [$($var,)*] = &tuple[..] else {
392                    return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
393                        actual: tuple.len(),
394                        expected: $count,
395                    }));
396                };
397
398                Ok(($(<$ty as FromValue>::from_value($var.clone())?,)*))
399            }
400        }
401
402        impl <$($ty,)*> FromConstValue for ($($ty,)*)
403        where
404            $($ty: FromConstValue,)*
405        {
406            fn from_const_value(value: ConstValue) -> Result<Self, RuntimeError> {
407                let tuple = value.into_tuple()?;
408
409                let [$($var,)*] = match <Box<[ConstValue; $count]>>::try_from(tuple) {
410                    Ok(tuple) => Box::into_inner(tuple),
411                    Err(tuple) => {
412                        return Err(RuntimeError::new(VmErrorKind::ExpectedTupleLength {
413                            actual: tuple.len(),
414                            expected: $count,
415                        }));
416                    }
417                };
418
419                Ok(($(<$ty as FromConstValue>::from_const_value($var)?,)*))
420            }
421        }
422
423        impl <$($ty,)*> ToValue for ($($ty,)*)
424        where
425            $($ty: ToValue,)*
426        {
427            fn to_value(self) -> Result<Value, RuntimeError> {
428                let ($($var,)*) = self;
429                $(let $var = $var.to_value()?;)*
430                let mut vec = alloc::Vec::try_with_capacity($count)?;
431                $(vec.try_push($var)?;)*
432                let tuple = OwnedTuple::try_from(vec)?;
433                Ok(Value::try_from(tuple)?)
434            }
435        }
436
437        impl <$($ty,)*> ToConstValue for ($($ty,)*)
438        where
439            $($ty: ToConstValue,)*
440        {
441            fn to_const_value(self) -> Result<ConstValue, RuntimeError> {
442                let ($($var,)*) = self;
443                $(let $var = $var.to_const_value()?;)*
444                let mut vec = alloc::Vec::try_with_capacity($count)?;
445                $(vec.try_push($var)?;)*
446                let tuple = Box::<[ConstValue]>::try_from(vec)?;
447                ConstValue::tuple(tuple)
448            }
449        }
450    };
451}
452
453repeat_macro!(impl_tuple);
454
455impl FromValue for Box<Tuple> {
456    #[inline]
457    fn from_value(value: Value) -> Result<Self, RuntimeError> {
458        value.into_tuple()
459    }
460}
461
462impl FromValue for Ref<Tuple> {
463    #[inline]
464    fn from_value(value: Value) -> Result<Self, RuntimeError> {
465        value.into_tuple_ref()
466    }
467}
468
469impl FromValue for Mut<Tuple> {
470    #[inline]
471    fn from_value(value: Value) -> Result<Self, RuntimeError> {
472        value.into_tuple_mut()
473    }
474}
475
476impl UnsafeToRef for Tuple {
477    type Guard = RawAnyGuard;
478
479    #[inline]
480    unsafe fn unsafe_to_ref<'a>(value: Value) -> Result<(&'a Self, Self::Guard), RuntimeError> {
481        let value = Ref::from_value(value)?;
482        let (value, guard) = Ref::into_raw(value);
483        Ok((value.as_ref(), guard))
484    }
485}
486
487impl UnsafeToMut for Tuple {
488    type Guard = RawAnyGuard;
489
490    #[inline]
491    unsafe fn unsafe_to_mut<'a>(value: Value) -> Result<(&'a mut Self, Self::Guard), RuntimeError> {
492        let value = Mut::from_value(value)?;
493        let (mut value, guard) = Mut::into_raw(value);
494        Ok((value.as_mut(), guard))
495    }
496}
497
498impl TryToOwned for Tuple {
499    type Owned = OwnedTuple;
500
501    #[inline]
502    fn try_to_owned(&self) -> alloc::Result<Self::Owned> {
503        let mut vec = alloc::Vec::try_with_capacity(self.len())?;
504
505        for value in self.iter() {
506            vec.try_push(value.clone())?;
507        }
508
509        OwnedTuple::try_from(vec)
510    }
511}