luau 0.732.0

Safe lifetime-bound Rust embedding API for the Luau runtime
use core::ops::{Deref, DerefMut};
use std::collections::{VecDeque, vec_deque};
use std::iter::FromIterator;

use crate::error::Error;
use crate::thread::Thread;
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Value};

/// A materialized sequence of Luau values used for function arguments and results.
pub struct MultiValue<'lua> {
    values: VecDeque<Value<'lua>>,
}

/// A materialized sequence of Luau values converted to a single Rust type.
///
/// `Variadic<T>` represents an arbitrary number of separate Luau arguments or
/// results rather than one Luau value.
#[derive(Debug, Clone)]
pub struct Variadic<T>(Vec<T>);

impl<'lua> MultiValue<'lua> {
    /// Creates an empty value sequence.
    pub fn new() -> Self {
        Self {
            values: VecDeque::new(),
        }
    }

    /// Creates an empty sequence with space for at least `capacity` values.
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            values: VecDeque::with_capacity(capacity),
        }
    }

    /// Creates a value sequence from a vector in argument order.
    pub fn from_vec(values: Vec<Value<'lua>>) -> Self {
        Self {
            values: values.into(),
        }
    }

    /// Returns the values as a vector in argument order.
    pub fn into_vec(self) -> Vec<Value<'lua>> {
        self.values.into()
    }

    /// Returns the number of values.
    pub fn len(&self) -> usize {
        self.values.len()
    }

    /// Returns whether the sequence contains no values.
    pub fn is_empty(&self) -> bool {
        self.values.is_empty()
    }

    /// Appends a value to the end of the sequence.
    pub fn push(&mut self, value: Value<'lua>) {
        self.values.push_back(value);
    }

    /// Removes and returns the first value.
    pub fn pop_front(&mut self) -> Option<Value<'lua>> {
        self.values.pop_front()
    }

    pub(crate) fn from_stack(
        thread: &Thread<'lua>,
        base_top: i32,
        count: i32,
    ) -> Result<Self, Error> {
        let mut values = Self::with_capacity(count.max(0) as usize);
        for offset in 0..count {
            values.push(Value::from_stack(thread, base_top + offset + 1)?);
        }
        Ok(values)
    }
}

impl Default for MultiValue<'_> {
    fn default() -> Self {
        Self::new()
    }
}

impl<'lua> From<Vec<Value<'lua>>> for MultiValue<'lua> {
    fn from(value: Vec<Value<'lua>>) -> Self {
        Self::from_vec(value)
    }
}

impl<'lua> From<MultiValue<'lua>> for Vec<Value<'lua>> {
    fn from(value: MultiValue<'lua>) -> Self {
        value.into_vec()
    }
}

impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
    fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
        Self {
            values: iter.into_iter().collect(),
        }
    }
}

impl<'lua> IntoIterator for MultiValue<'lua> {
    type Item = Value<'lua>;
    type IntoIter = vec_deque::IntoIter<Value<'lua>>;

    fn into_iter(self) -> Self::IntoIter {
        self.values.into_iter()
    }
}

impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
    type Item = &'a Value<'lua>;
    type IntoIter = vec_deque::Iter<'a, Value<'lua>>;

    fn into_iter(self) -> Self::IntoIter {
        self.values.iter()
    }
}

impl<'lua> IntoLuaMulti<'lua> for MultiValue<'lua> {
    fn into_lua_multi(self, _: crate::LuaRef<'lua>) -> Result<MultiValue<'lua>, Error> {
        Ok(self)
    }
}

impl<'lua, 'value> IntoLuaMulti<'lua> for &MultiValue<'value>
where
    'value: 'lua,
{
    fn into_lua_multi(self, _: crate::LuaRef<'lua>) -> Result<MultiValue<'lua>, Error> {
        self.into_iter().map(Value::try_clone).collect()
    }

    unsafe fn push_into_stack_multi(self, thread: &Thread<'lua>) -> Result<usize, Error> {
        thread.reserve_stack(self.len())?;
        for value in self {
            value.push_to(thread)?;
        }
        Ok(self.len())
    }
}

impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> {
    fn from_lua_multi(values: MultiValue<'lua>, _: crate::LuaRef<'lua>) -> Result<Self, Error> {
        Ok(values)
    }

    unsafe fn from_stack_multi(
        thread: &Thread<'lua>,
        base_top: i32,
        count: i32,
    ) -> Result<Self, Error> {
        MultiValue::from_stack(thread, base_top, count)
    }
}

impl<T> Variadic<T> {
    /// Creates an empty variadic value sequence.
    pub const fn new() -> Self {
        Self(Vec::new())
    }

    /// Creates an empty sequence with space for at least `capacity` values.
    pub fn with_capacity(capacity: usize) -> Self {
        Self(Vec::with_capacity(capacity))
    }

    /// Wraps an existing vector as a sequence of separate Lua values.
    pub fn from_vec(values: Vec<T>) -> Self {
        Self(values)
    }

    /// Returns the underlying materialized values.
    pub fn into_vec(self) -> Vec<T> {
        self.0
    }
}

impl<T> Default for Variadic<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Deref for Variadic<T> {
    type Target = Vec<T>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for Variadic<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> From<Vec<T>> for Variadic<T> {
    fn from(values: Vec<T>) -> Self {
        Self::from_vec(values)
    }
}

impl<T> From<Variadic<T>> for Vec<T> {
    fn from(values: Variadic<T>) -> Self {
        values.into_vec()
    }
}

impl<T> FromIterator<T> for Variadic<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        Self(iter.into_iter().collect())
    }
}

impl<T> IntoIterator for Variadic<T> {
    type Item = T;
    type IntoIter = std::vec::IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<'a, T> IntoIterator for &'a Variadic<T> {
    type Item = &'a T;
    type IntoIter = std::slice::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Variadic<T> {
    type Item = &'a mut T;
    type IntoIter = std::slice::IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}

impl<'lua, T> IntoLuaMulti<'lua> for Variadic<T>
where
    T: IntoLua<'lua>,
{
    fn into_lua_multi(self, thread: crate::LuaRef<'lua>) -> Result<MultiValue<'lua>, Error> {
        self.into_iter()
            .map(|value| value.into_lua(thread))
            .collect()
    }

    unsafe fn push_into_stack_multi(self, thread: &Thread<'lua>) -> Result<usize, Error> {
        let count = self.len();
        thread.reserve_stack(count)?;
        for value in self {
            unsafe {
                value.push_into_stack(thread)?;
            }
        }
        Ok(count)
    }
}

impl<'lua, T> FromLuaMulti<'lua> for Variadic<T>
where
    T: FromLua<'lua>,
{
    fn from_lua_multi(
        values: MultiValue<'lua>,
        thread: crate::LuaRef<'lua>,
    ) -> Result<Self, Error> {
        values
            .into_iter()
            .map(|value| T::from_lua(value, thread))
            .collect()
    }

    unsafe fn from_stack_multi(
        thread: &Thread<'lua>,
        base_top: i32,
        count: i32,
    ) -> Result<Self, Error> {
        let count = count.max(0);
        let mut values = Self::with_capacity(count as usize);
        for offset in 0..count {
            values
                .0
                .push(unsafe { T::from_stack(thread, base_top + offset + 1)? });
        }
        Ok(values)
    }
}