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, Mut, RawAnyGuard, Ref,
17    RuntimeError, ToConstValue, ToValue, UnsafeToMut, UnsafeToRef, Value, VmErrorKind, VmResult,
18};
19#[cfg(feature = "alloc")]
20use super::{Hasher, ProtocolCaller};
21
22/// The type of a tuple slice.
23#[repr(transparent)]
24pub struct Tuple {
25    values: [Value],
26}
27
28impl Tuple {
29    /// Construct a new tuple slice from a reference.
30    pub const fn new(values: &[Value]) -> &Self {
31        // SAFETY: Tuple is repr transparent over [Value].
32        unsafe { &*(values as *const _ as *const Self) }
33    }
34
35    /// Construct a boxed tuple over a boxed slice of values.
36    pub(crate) fn from_boxed(boxed: Box<[Value]>) -> Box<Self> {
37        let (values, Global) = Box::into_raw_with_allocator(boxed);
38        // SAFETY: Tuple is repr transparent over [Value].
39        unsafe { Box::from_raw_in(values as *mut Tuple, Global) }
40    }
41
42    /// Construct a new tuple slice from a mutable reference.
43    pub fn new_mut(values: &mut [Value]) -> &mut Self {
44        // SAFETY: Tuple is repr transparent over [Value].
45        unsafe { &mut *(values as *mut _ as *mut Self) }
46    }
47
48    /// Get the given value at the given index.
49    pub fn get_value<T>(&self, index: usize) -> VmResult<Option<T>>
50    where
51        T: FromValue,
52    {
53        let value = match self.values.get(index) {
54            Some(value) => value.clone(),
55            None => return VmResult::Ok(None),
56        };
57
58        VmResult::Ok(Some(vm_try!(T::from_value(value))))
59    }
60
61    pub(crate) fn hash_with(
62        &self,
63        hasher: &mut Hasher,
64        caller: &mut dyn ProtocolCaller,
65    ) -> VmResult<()> {
66        for value in self.values.iter() {
67            vm_try!(value.hash_with(hasher, caller));
68        }
69
70        VmResult::Ok(())
71    }
72
73    pub(crate) fn debug_fmt_with(
74        &self,
75        f: &mut Formatter,
76        caller: &mut dyn ProtocolCaller,
77    ) -> VmResult<()> {
78        let mut it = self.iter().peekable();
79        vm_try!(vm_write!(f, "("));
80
81        while let Some(value) = it.next() {
82            vm_try!(value.debug_fmt_with(f, caller));
83
84            if it.peek().is_some() {
85                vm_try!(vm_write!(f, ", "));
86            }
87        }
88
89        vm_try!(vm_write!(f, ")"));
90        VmResult::Ok(())
91    }
92
93    pub(crate) fn clone_with(&self, caller: &mut dyn ProtocolCaller) -> VmResult<OwnedTuple> {
94        let mut vec = vm_try!(alloc::Vec::try_with_capacity(self.len()));
95
96        for value in self.values.iter() {
97            let value = vm_try!(value.clone_with(caller));
98            vm_try!(vec.try_push(value));
99        }
100
101        VmResult::Ok(vm_try!(OwnedTuple::try_from(vec)))
102    }
103}
104
105impl ops::Deref for Tuple {
106    type Target = [Value];
107
108    #[inline]
109    fn deref(&self) -> &Self::Target {
110        &self.values
111    }
112}
113
114impl ops::DerefMut for Tuple {
115    #[inline]
116    fn deref_mut(&mut self) -> &mut Self::Target {
117        &mut self.values
118    }
119}
120
121impl<'a> IntoIterator for &'a Tuple {
122    type Item = &'a Value;
123    type IntoIter = slice::Iter<'a, Value>;
124
125    #[inline]
126    fn into_iter(self) -> Self::IntoIter {
127        self.iter()
128    }
129}
130
131impl<'a> IntoIterator for &'a mut Tuple {
132    type Item = &'a mut Value;
133    type IntoIter = slice::IterMut<'a, Value>;
134
135    #[inline]
136    fn into_iter(self) -> Self::IntoIter {
137        self.iter_mut()
138    }
139}
140
141/// Struct representing a dynamic anonymous object.
142///
143/// To access borrowed values of a tuple in native functions, use [`Tuple`].
144#[derive(Any)]
145#[rune(item = ::std::tuple, name = Tuple)]
146#[repr(transparent)]
147pub struct OwnedTuple {
148    inner: Box<[Value]>,
149}
150
151impl OwnedTuple {
152    /// Construct a new empty tuple.
153    ///
154    /// # Examples
155    ///
156    /// ```
157    /// use rune::runtime::OwnedTuple;
158    ///
159    /// let empty = OwnedTuple::new();
160    /// ```
161    pub fn new() -> Self {
162        Self {
163            inner: Box::default(),
164        }
165    }
166
167    /// Coerce this owned tuple into a boxed tuple.
168    pub fn into_boxed_tuple(self) -> Box<Tuple> {
169        Tuple::from_boxed(self.inner)
170    }
171
172    /// Convert into inner std boxed slice.
173    pub fn into_inner(self) -> Box<[Value]> {
174        self.inner
175    }
176}
177
178impl Deref for OwnedTuple {
179    type Target = Tuple;
180
181    #[inline]
182    fn deref(&self) -> &Self::Target {
183        Tuple::new(&self.inner)
184    }
185}
186
187impl DerefMut for OwnedTuple {
188    #[inline]
189    fn deref_mut(&mut self) -> &mut Self::Target {
190        Tuple::new_mut(&mut self.inner)
191    }
192}
193
194impl AsRef<Tuple> for OwnedTuple {
195    #[inline]
196    fn as_ref(&self) -> &Tuple {
197        self
198    }
199}
200
201impl AsMut<Tuple> for OwnedTuple {
202    #[inline]
203    fn as_mut(&mut self) -> &mut Tuple {
204        self
205    }
206}
207
208impl Borrow<Tuple> for OwnedTuple {
209    #[inline]
210    fn borrow(&self) -> &Tuple {
211        self
212    }
213}
214
215impl Default for OwnedTuple {
216    fn default() -> Self {
217        Self::new()
218    }
219}
220
221impl TryClone for OwnedTuple {
222    #[inline]
223    fn try_clone(&self) -> alloc::Result<Self> {
224        Ok(Self {
225            inner: self.inner.try_clone()?,
226        })
227    }
228
229    #[inline]
230    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
231        self.inner.try_clone_from(&source.inner)
232    }
233}
234
235impl fmt::Debug for OwnedTuple {
236    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
237        write!(f, "(")?;
238
239        let mut it = self.iter();
240        let last = it.next_back();
241
242        for el in it {
243            write!(f, "{:?}, ", el)?;
244        }
245
246        if let Some(last) = last {
247            write!(f, "{:?}", last)?;
248        }
249
250        write!(f, ")")?;
251        Ok(())
252    }
253}
254
255#[cfg(feature = "alloc")]
256impl TryFrom<::rust_alloc::vec::Vec<Value>> for OwnedTuple {
257    type Error = alloc::Error;
258
259    #[inline]
260    fn try_from(vec: ::rust_alloc::vec::Vec<Value>) -> Result<Self, Self::Error> {
261        Ok(Self {
262            inner: alloc::Box::try_from(vec.into_boxed_slice())?,
263        })
264    }
265}
266
267impl TryFrom<alloc::Vec<Value>> for OwnedTuple {
268    type Error = alloc::Error;
269
270    #[inline]
271    fn try_from(vec: alloc::Vec<Value>) -> Result<Self, Self::Error> {
272        Ok(Self {
273            inner: vec.try_into_boxed_slice()?,
274        })
275    }
276}
277
278impl<const N: usize> TryFrom<[Value; N]> for OwnedTuple {
279    type Error = alloc::Error;
280
281    #[inline]
282    fn try_from(values: [Value; N]) -> Result<Self, Self::Error> {
283        Ok(Self {
284            inner: values.try_into()?,
285        })
286    }
287}
288
289impl From<alloc::Box<[Value]>> for OwnedTuple {
290    #[inline]
291    fn from(inner: alloc::Box<[Value]>) -> Self {
292        Self { inner }
293    }
294}
295
296impl TryFrom<alloc::Box<[ConstValue]>> for OwnedTuple {
297    type Error = RuntimeError;
298
299    fn try_from(inner: alloc::Box<[ConstValue]>) -> Result<Self, RuntimeError> {
300        if inner.is_empty() {
301            return Ok(OwnedTuple::new());
302        }
303
304        let mut out = alloc::Vec::try_with_capacity(inner.len())?;
305
306        for value in inner.iter() {
307            out.try_push(value.to_value_with(&EmptyConstContext)?)?;
308        }
309
310        Ok(Self {
311            inner: out.try_into_boxed_slice()?,
312        })
313    }
314}
315
316#[cfg(feature = "alloc")]
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
328#[cfg(feature = "alloc")]
329impl TryFrom<::rust_alloc::boxed::Box<[ConstValue]>> for OwnedTuple {
330    type Error = RuntimeError;
331
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                Ok(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}