use std::{
collections::{VecDeque, vec_deque},
ops::{Deref, DerefMut},
};
use crate::lua::{
self, FromLuaMulti, Result, ToLuaMulti, ffi,
traits::{FromLua, ToLua},
value_ref::ValueRef,
};
#[derive(Clone, Debug)]
pub struct Value {
pub(crate) type_id: i32,
pub(crate) inner: ValueRef,
}
#[derive(Debug)]
pub enum ValueKind {
Nil,
Bool,
LightUserData,
Number,
String,
Table,
Function,
UserData,
Thread,
Unknown,
}
impl Value {
pub fn from_stack(state: &lua::State, index: i32) -> Self {
ffi::lua_pushvalue(state.0, index);
Self::pop_from_stack(state)
}
pub fn pop_from_stack(state: &lua::State) -> Self {
let type_id = ffi::lua_type(state.0, -1);
Self {
type_id,
inner: ValueRef::pop_from(state),
}
}
pub fn type_id(&self) -> i32 {
self.type_id
}
pub fn type_kind(&self) -> ValueKind {
match self.type_id {
ffi::LUA_TNIL | ffi::LUA_TNONE => ValueKind::Nil,
ffi::LUA_TBOOLEAN => ValueKind::Bool,
ffi::LUA_TLIGHTUSERDATA => ValueKind::LightUserData,
ffi::LUA_TNUMBER => ValueKind::Number,
ffi::LUA_TSTRING => ValueKind::String,
ffi::LUA_TTABLE => ValueKind::Table,
ffi::LUA_TFUNCTION => ValueKind::Function,
ffi::LUA_TUSERDATA => ValueKind::UserData,
ffi::LUA_TTHREAD => ValueKind::Thread,
_ => ValueKind::Unknown,
}
}
pub fn push_to_stack(&self, state: &lua::State) {
self.inner.push(state);
}
pub(crate) fn index(&self) -> i32 {
self.inner.index
}
pub(crate) fn thread(&self) -> lua::State {
self.inner.thread()
}
}
impl ToLua for Value {
fn push_to_stack(self, state: &lua::State) {
Value::push_to_stack(&self, state);
}
fn to_value(self, _: &lua::State) -> Value {
self
}
}
impl ToLua for &Value {
fn push_to_stack(self, state: &lua::State) {
Value::push_to_stack(self, state);
}
fn to_value(self, _: &lua::State) -> Value {
self.clone()
}
}
impl FromLua for Value {
fn try_from_stack(state: &lua::State, index: i32) -> Result<Self> {
Ok(Self::from_stack(state, index))
}
fn try_from_value(value: Value, _: &lua::State) -> Result<Self> {
Ok(value)
}
}
#[derive(Default, Debug, Clone)]
pub struct MultiValue(VecDeque<Value>);
impl Deref for MultiValue {
type Target = VecDeque<Value>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for MultiValue {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl MultiValue {
#[inline]
pub const fn new() -> MultiValue {
MultiValue(VecDeque::new())
}
pub fn with_capacity(capacity: usize) -> MultiValue {
MultiValue(VecDeque::with_capacity(capacity))
}
#[inline]
pub fn from_vec(vec: Vec<Value>) -> MultiValue {
vec.into()
}
#[inline]
pub fn into_vec(self) -> Vec<Value> {
self.into()
}
#[allow(unused)]
#[inline]
pub(crate) fn from_lua_iter<T: ToLua>(
state: &lua::State,
iter: impl IntoIterator<Item = T>,
) -> Result<Self> {
let iter = iter.into_iter();
let mut multi_value = MultiValue::with_capacity(iter.size_hint().0);
for value in iter {
multi_value.push_back(value.to_value(state));
}
Ok(multi_value)
}
}
impl From<Vec<Value>> for MultiValue {
#[inline]
fn from(value: Vec<Value>) -> Self {
MultiValue(value.into())
}
}
impl From<MultiValue> for Vec<Value> {
#[inline]
fn from(value: MultiValue) -> Self {
value.0.into()
}
}
impl FromIterator<Value> for MultiValue {
#[inline]
fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
let mut multi_value = MultiValue::new();
multi_value.extend(iter);
multi_value
}
}
impl IntoIterator for MultiValue {
type Item = Value;
type IntoIter = vec_deque::IntoIter<Value>;
#[inline]
fn into_iter(mut self) -> Self::IntoIter {
let deque = std::mem::take(&mut self.0);
std::mem::forget(self);
deque.into_iter()
}
}
impl ToLuaMulti for MultiValue {
fn push_to_stack_multi(self, state: &lua::State) {
for value in self {
value.push_to_stack(state);
}
}
}
impl FromLuaMulti for MultiValue {
fn try_from_stack_multi(
state: &lua::State,
start_index: i32,
count: i32,
) -> Result<(Self, i32)> {
let mut multi_value = MultiValue::with_capacity(count as usize);
for i in 0..count {
multi_value.push_back(Value::from_stack(state, start_index + i));
}
Ok((multi_value, count))
}
}