1use std::iter::{self, FromIterator};
2use std::os::raw::c_void;
3use std::{ptr, slice, str, vec};
4
5#[cfg(feature = "serialize")]
6use {
7 serde::ser::{self, Serialize, Serializer},
8 std::convert::TryInto,
9 std::result::Result as StdResult,
10};
11
12use crate::error::{Error, Result};
13use crate::ffi;
14use crate::function::Function;
15use crate::lua::Lua;
16use crate::string::String;
17use crate::table::Table;
18use crate::thread::Thread;
19use crate::types::{Integer, LightUserData, Number};
20use crate::userdata::AnyUserData;
21
22#[derive(Debug, Clone)]
26pub enum Value<'lua> {
27 Nil,
29 Boolean(bool),
31 LightUserData(LightUserData),
33 Integer(Integer),
37 Number(Number),
39 #[cfg(any(feature = "luau", doc))]
41 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
42 Vector(f32, f32, f32),
43 String(String<'lua>),
47 Table(Table<'lua>),
49 Function(Function<'lua>),
51 Thread(Thread<'lua>),
53 UserData(AnyUserData<'lua>),
56 Error(Error),
58}
59
60pub use self::Value::Nil;
61
62impl<'lua> Value<'lua> {
63 pub const fn type_name(&self) -> &'static str {
64 match *self {
65 Value::Nil => "nil",
66 Value::Boolean(_) => "boolean",
67 Value::LightUserData(_) => "lightuserdata",
68 Value::Integer(_) => "integer",
69 Value::Number(_) => "number",
70 #[cfg(feature = "luau")]
71 Value::Vector(_, _, _) => "vector",
72 Value::String(_) => "string",
73 Value::Table(_) => "table",
74 Value::Function(_) => "function",
75 Value::Thread(_) => "thread",
76 Value::UserData(_) => "userdata",
77 Value::Error(_) => "error",
78 }
79 }
80
81 pub fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
92 match (self, other.as_ref()) {
93 (Value::Table(a), Value::Table(b)) => a.equals(b),
94 (Value::UserData(a), Value::UserData(b)) => a.equals(b),
95 _ => Ok(self == other.as_ref()),
96 }
97 }
98
99 pub fn to_pointer(&self) -> *const c_void {
107 unsafe {
108 match self {
109 Value::LightUserData(ud) => ud.0,
110 Value::String(String(v))
111 | Value::Table(Table(v))
112 | Value::Function(Function(v))
113 | Value::Thread(Thread(v))
114 | Value::UserData(AnyUserData(v)) => v
115 .lua
116 .ref_thread_exec(|refthr| ffi::lua_topointer(refthr, v.index)),
117 _ => ptr::null(),
118 }
119 }
120 }
121}
122
123impl<'lua> PartialEq for Value<'lua> {
124 fn eq(&self, other: &Self) -> bool {
125 match (self, other) {
126 (Value::Nil, Value::Nil) => true,
127 (Value::Boolean(a), Value::Boolean(b)) => a == b,
128 (Value::LightUserData(a), Value::LightUserData(b)) => a == b,
129 (Value::Integer(a), Value::Integer(b)) => *a == *b,
130 (Value::Integer(a), Value::Number(b)) => *a as Number == *b,
131 (Value::Number(a), Value::Integer(b)) => *a == *b as Number,
132 (Value::Number(a), Value::Number(b)) => *a == *b,
133 #[cfg(feature = "luau")]
134 (Value::Vector(x1, y1, z1), Value::Vector(x2, y2, z2)) => (x1, y1, z1) == (x2, y2, z2),
135 (Value::String(a), Value::String(b)) => a == b,
136 (Value::Table(a), Value::Table(b)) => a == b,
137 (Value::Function(a), Value::Function(b)) => a == b,
138 (Value::Thread(a), Value::Thread(b)) => a == b,
139 (Value::UserData(a), Value::UserData(b)) => a == b,
140 _ => false,
141 }
142 }
143}
144
145impl<'lua> AsRef<Value<'lua>> for Value<'lua> {
146 #[inline]
147 fn as_ref(&self) -> &Self {
148 self
149 }
150}
151
152#[cfg(feature = "serialize")]
153impl<'lua> Serialize for Value<'lua> {
154 fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
155 where
156 S: Serializer,
157 {
158 match self {
159 Value::Nil => serializer.serialize_unit(),
160 Value::Boolean(b) => serializer.serialize_bool(*b),
161 #[allow(clippy::useless_conversion)]
162 Value::Integer(i) => serializer
163 .serialize_i64((*i).try_into().expect("cannot convert lua_Integer to i64")),
164 #[allow(clippy::useless_conversion)]
165 Value::Number(n) => serializer.serialize_f64(*n),
166 #[cfg(feature = "luau")]
167 Value::Vector(x, y, z) => (x, y, z).serialize(serializer),
168 Value::String(s) => s.serialize(serializer),
169 Value::Table(t) => t.serialize(serializer),
170 Value::UserData(ud) => ud.serialize(serializer),
171 Value::LightUserData(ud) if ud.0.is_null() => serializer.serialize_none(),
172 Value::Error(_) | Value::LightUserData(_) | Value::Function(_) | Value::Thread(_) => {
173 let msg = format!("cannot serialize <{}>", self.type_name());
174 Err(ser::Error::custom(msg))
175 }
176 }
177 }
178}
179
180pub trait ToLua<'lua> {
182 fn to_lua(self, lua: &'lua Lua) -> Result<Value<'lua>>;
184}
185
186pub trait FromLua<'lua>: Sized {
188 fn from_lua(lua_value: Value<'lua>, lua: &'lua Lua) -> Result<Self>;
190}
191
192#[derive(Debug, Clone)]
194pub struct MultiValue<'lua>(Vec<Value<'lua>>);
195
196impl<'lua> MultiValue<'lua> {
197 #[inline]
199 pub const fn new() -> MultiValue<'lua> {
200 MultiValue(Vec::new())
201 }
202
203 #[inline]
205 pub(crate) fn new_or_cached(lua: &'lua Lua) -> MultiValue<'lua> {
206 lua.new_or_cached_multivalue()
207 }
208}
209
210impl<'lua> Default for MultiValue<'lua> {
211 #[inline]
212 fn default() -> MultiValue<'lua> {
213 MultiValue::new()
214 }
215}
216
217impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
218 #[inline]
219 fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
220 MultiValue::from_vec(Vec::from_iter(iter))
221 }
222}
223
224impl<'lua> IntoIterator for MultiValue<'lua> {
225 type Item = Value<'lua>;
226 type IntoIter = iter::Rev<vec::IntoIter<Value<'lua>>>;
227
228 #[inline]
229 fn into_iter(self) -> Self::IntoIter {
230 self.0.into_iter().rev()
231 }
232}
233
234impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
235 type Item = &'a Value<'lua>;
236 type IntoIter = iter::Rev<slice::Iter<'a, Value<'lua>>>;
237
238 #[inline]
239 fn into_iter(self) -> Self::IntoIter {
240 (&self.0).iter().rev()
241 }
242}
243
244impl<'lua> MultiValue<'lua> {
245 #[inline]
246 pub fn from_vec(mut v: Vec<Value<'lua>>) -> MultiValue<'lua> {
247 v.reverse();
248 MultiValue(v)
249 }
250
251 #[inline]
252 pub fn into_vec(self) -> Vec<Value<'lua>> {
253 let mut v = self.0;
254 v.reverse();
255 v
256 }
257
258 #[inline]
259 pub(crate) fn reserve(&mut self, size: usize) {
260 self.0.reserve(size);
261 }
262
263 #[inline]
264 pub(crate) fn push_front(&mut self, value: Value<'lua>) {
265 self.0.push(value);
266 }
267
268 #[inline]
269 pub(crate) fn pop_front(&mut self) -> Option<Value<'lua>> {
270 self.0.pop()
271 }
272
273 #[inline]
274 pub fn clear(&mut self) {
275 self.0.clear();
276 }
277
278 #[inline]
279 pub fn len(&self) -> usize {
280 self.0.len()
281 }
282
283 #[inline]
284 pub fn is_empty(&self) -> bool {
285 self.0.is_empty()
286 }
287
288 #[inline]
289 pub fn iter(&self) -> iter::Rev<slice::Iter<Value<'lua>>> {
290 self.0.iter().rev()
291 }
292
293 #[inline]
294 pub(crate) fn drain_all(&mut self) -> iter::Rev<vec::Drain<Value<'lua>>> {
295 self.0.drain(..).rev()
296 }
297
298 #[inline]
299 pub(crate) fn refill(
300 &mut self,
301 iter: impl IntoIterator<Item = Result<Value<'lua>>>,
302 ) -> Result<()> {
303 self.0.clear();
304 for value in iter {
305 self.0.push(value?);
306 }
307 self.0.reverse();
308 Ok(())
309 }
310}
311
312pub trait ToLuaMulti<'lua> {
317 fn to_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>>;
319}
320
321pub trait FromLuaMulti<'lua>: Sized {
326 fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
333}