1use std::borrow::Cow;
2use std::cmp::Ordering;
3use std::collections::HashSet;
4use std::iter;
5use std::ops::Index;
6use std::os::raw::{c_int, c_void};
7use std::string::String as StdString;
8use std::sync::Arc;
9use std::{fmt, mem, ptr, slice, str, vec};
10
11use num_traits::FromPrimitive;
12
13#[cfg(feature = "serialize")]
14use {
15 crate::table::SerializableTable,
16 rustc_hash::FxHashSet,
17 serde::ser::{self, Serialize, Serializer},
18 std::{cell::RefCell, rc::Rc, result::Result as StdResult},
19};
20
21use crate::error::{Error, Result};
22use crate::function::Function;
23use crate::lua::Lua;
24use crate::string::String;
25use crate::table::Table;
26use crate::thread::Thread;
27use crate::types::{Integer, LightUserData, Number, SubtypeId};
28use crate::userdata::AnyUserData;
29use crate::util::{check_stack, StackGuard};
30
31#[derive(Clone)]
35pub enum Value<'lua> {
36 Nil,
38 Boolean(bool),
40 LightUserData(LightUserData),
42 Integer(Integer),
46 Number(Number),
48 #[cfg(any(feature = "luau", doc))]
50 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
51 Vector(crate::types::Vector),
52 String(String<'lua>),
56 Table(Table<'lua>),
58 Function(Function<'lua>),
60 Thread(Thread<'lua>),
62 UserData(AnyUserData<'lua>),
65 Error(Error),
67}
68
69pub use self::Value::Nil;
70
71impl<'lua> Value<'lua> {
72 pub const NULL: Value<'static> = Value::LightUserData(LightUserData(ptr::null_mut()));
76
77 pub const fn type_name(&self) -> &'static str {
79 match *self {
80 Value::Nil => "nil",
81 Value::Boolean(_) => "boolean",
82 Value::LightUserData(_) => "lightuserdata",
83 Value::Integer(_) => "integer",
84 Value::Number(_) => "number",
85 #[cfg(feature = "luau")]
86 Value::Vector(_) => "vector",
87 Value::String(_) => "string",
88 Value::Table(_) => "table",
89 Value::Function(_) => "function",
90 Value::Thread(_) => "thread",
91 Value::UserData(AnyUserData(_, SubtypeId::None)) => "userdata",
92 #[cfg(feature = "luau")]
93 Value::UserData(AnyUserData(_, SubtypeId::Buffer)) => "buffer",
94 #[cfg(feature = "luajit")]
95 Value::UserData(AnyUserData(_, SubtypeId::CData)) => "cdata",
96 Value::Error(_) => "error",
97 }
98 }
99
100 pub fn equals<T: AsRef<Self>>(&self, other: T) -> Result<bool> {
111 match (self, other.as_ref()) {
112 (Value::Table(a), Value::Table(b)) => a.equals(b),
113 (Value::UserData(a), Value::UserData(b)) => a.equals(b),
114 (a, b) => Ok(a == b),
115 }
116 }
117
118 #[inline]
126 pub fn to_pointer(&self) -> *const c_void {
127 match self {
128 Value::LightUserData(ud) => ud.0,
129 Value::String(String(r))
130 | Value::Table(Table(r))
131 | Value::Function(Function(r))
132 | Value::Thread(Thread(r, ..))
133 | Value::UserData(AnyUserData(r, ..)) => r.to_pointer(),
134 _ => ptr::null(),
135 }
136 }
137
138 pub fn to_string(&self) -> Result<StdString> {
142 match self {
143 Value::Nil => Ok("nil".to_string()),
144 Value::Boolean(b) => Ok(b.to_string()),
145 Value::LightUserData(ud) if ud.0.is_null() => Ok("null".to_string()),
146 Value::LightUserData(ud) => Ok(format!("lightuserdata: {:p}", ud.0)),
147 Value::Integer(i) => Ok(i.to_string()),
148 Value::Number(n) => Ok(n.to_string()),
149 #[cfg(feature = "luau")]
150 Value::Vector(v) => Ok(v.to_string()),
151 Value::String(s) => Ok(s.to_str()?.to_string()),
152 Value::Table(Table(r))
153 | Value::Function(Function(r))
154 | Value::Thread(Thread(r, ..))
155 | Value::UserData(AnyUserData(r, ..)) => unsafe {
156 let state = r.lua.state();
157 let _guard = StackGuard::new(state);
158 check_stack(state, 3)?;
159
160 r.lua.push_ref(r);
161 protect_lua!(state, 1, 1, fn(state) {
162 ffi::luaL_tolstring(state, -1, ptr::null_mut());
163 })?;
164 Ok(String(r.lua.pop_ref()).to_str()?.to_string())
165 },
166 Value::Error(err) => Ok(err.to_string()),
167 }
168 }
169
170 #[inline]
172 pub fn is_nil(&self) -> bool {
173 self == &Nil
174 }
175
176 #[inline]
178 pub fn is_null(&self) -> bool {
179 self == &Self::NULL
180 }
181
182 #[inline]
184 pub fn is_boolean(&self) -> bool {
185 self.as_boolean().is_some()
186 }
187
188 #[inline]
192 pub fn as_boolean(&self) -> Option<bool> {
193 match *self {
194 Value::Boolean(b) => Some(b),
195 _ => None,
196 }
197 }
198
199 #[inline]
201 pub fn is_light_userdata(&self) -> bool {
202 self.as_light_userdata().is_some()
203 }
204
205 #[inline]
209 pub fn as_light_userdata(&self) -> Option<LightUserData> {
210 match *self {
211 Value::LightUserData(l) => Some(l),
212 _ => None,
213 }
214 }
215
216 #[inline]
218 pub fn is_integer(&self) -> bool {
219 self.as_integer().is_some()
220 }
221
222 #[inline]
226 pub fn as_integer(&self) -> Option<Integer> {
227 match *self {
228 Value::Integer(i) => Some(i),
229 _ => None,
230 }
231 }
232
233 #[inline]
237 pub fn as_i32(&self) -> Option<i32> {
238 #[allow(clippy::useless_conversion)]
239 self.as_integer().and_then(|i| i32::try_from(i).ok())
240 }
241
242 #[inline]
246 pub fn as_u32(&self) -> Option<u32> {
247 self.as_integer().and_then(|i| u32::try_from(i).ok())
248 }
249
250 #[inline]
254 pub fn as_i64(&self) -> Option<i64> {
255 self.as_integer().map(i64::from)
256 }
257
258 #[inline]
262 pub fn as_u64(&self) -> Option<u64> {
263 self.as_integer().and_then(|i| u64::try_from(i).ok())
264 }
265
266 #[inline]
270 pub fn as_isize(&self) -> Option<isize> {
271 self.as_integer().and_then(|i| isize::try_from(i).ok())
272 }
273
274 #[inline]
278 pub fn as_usize(&self) -> Option<usize> {
279 self.as_integer().and_then(|i| usize::try_from(i).ok())
280 }
281
282 #[inline]
284 pub fn is_number(&self) -> bool {
285 self.as_number().is_some()
286 }
287
288 #[inline]
292 pub fn as_number(&self) -> Option<Number> {
293 match *self {
294 Value::Number(n) => Some(n),
295 _ => None,
296 }
297 }
298
299 #[inline]
303 pub fn as_f32(&self) -> Option<f32> {
304 self.as_number().and_then(f32::from_f64)
305 }
306
307 #[inline]
311 pub fn as_f64(&self) -> Option<f64> {
312 self.as_number()
313 }
314
315 #[inline]
317 pub fn is_string(&self) -> bool {
318 self.as_string().is_some()
319 }
320
321 #[inline]
325 pub fn as_string(&self) -> Option<&String> {
326 match self {
327 Value::String(s) => Some(s),
328 _ => None,
329 }
330 }
331
332 #[inline]
336 pub fn as_str(&self) -> Option<&str> {
337 self.as_string().and_then(|s| s.to_str().ok())
338 }
339
340 #[inline]
344 pub fn as_string_lossy(&self) -> Option<Cow<str>> {
345 self.as_string().map(|s| s.to_string_lossy())
346 }
347
348 #[inline]
350 pub fn is_table(&self) -> bool {
351 self.as_table().is_some()
352 }
353
354 #[inline]
358 pub fn as_table(&self) -> Option<&Table> {
359 match self {
360 Value::Table(t) => Some(t),
361 _ => None,
362 }
363 }
364
365 #[inline]
367 pub fn is_thread(&self) -> bool {
368 self.as_thread().is_some()
369 }
370
371 #[inline]
375 pub fn as_thread(&self) -> Option<&Thread> {
376 match self {
377 Value::Thread(t) => Some(t),
378 _ => None,
379 }
380 }
381
382 #[inline]
384 pub fn is_function(&self) -> bool {
385 self.as_function().is_some()
386 }
387
388 #[inline]
392 pub fn as_function(&self) -> Option<&Function> {
393 match self {
394 Value::Function(f) => Some(f),
395 _ => None,
396 }
397 }
398
399 #[inline]
401 pub fn is_userdata(&self) -> bool {
402 self.as_userdata().is_some()
403 }
404
405 #[inline]
409 pub fn as_userdata(&self) -> Option<&AnyUserData> {
410 match self {
411 Value::UserData(ud) => Some(ud),
412 _ => None,
413 }
414 }
415
416 #[cfg(any(feature = "luau", doc))]
418 #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
419 #[doc(hidden)]
420 #[inline]
421 pub fn is_buffer(&self) -> bool {
422 self.as_userdata()
423 .map(|ud| ud.1 == SubtypeId::Buffer)
424 .unwrap_or_default()
425 }
426
427 #[cfg(any(feature = "luajit", doc))]
429 #[cfg_attr(docsrs, doc(cfg(feature = "luajit")))]
430 #[doc(hidden)]
431 #[inline]
432 pub fn is_cdata(&self) -> bool {
433 self.as_userdata()
434 .map(|ud| ud.1 == SubtypeId::CData)
435 .unwrap_or_default()
436 }
437
438 #[cfg(feature = "serialize")]
442 #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
443 #[doc(hidden)]
444 pub fn to_serializable(&self) -> SerializableValue<'_, 'lua> {
445 SerializableValue::new(self, Default::default(), None)
446 }
447
448 pub(crate) fn cmp(&self, other: &Self) -> Ordering {
451 fn cmp_num(a: Number, b: Number) -> Ordering {
452 match (a, b) {
453 _ if a < b => Ordering::Less,
454 _ if a > b => Ordering::Greater,
455 _ => Ordering::Equal,
456 }
457 }
458
459 match (self, other) {
460 (Value::Nil, Value::Nil) => Ordering::Equal,
462 (Value::Nil, _) => Ordering::Less,
463 (_, Value::Nil) => Ordering::Greater,
464 (Value::LightUserData(ud1), Value::LightUserData(ud2)) if ud1 == ud2 => Ordering::Equal,
466 (Value::LightUserData(ud1), _) if ud1.0.is_null() => Ordering::Less,
467 (_, Value::LightUserData(ud2)) if ud2.0.is_null() => Ordering::Greater,
468 (Value::Boolean(a), Value::Boolean(b)) => a.cmp(b),
470 (Value::Boolean(_), _) => Ordering::Less,
471 (_, Value::Boolean(_)) => Ordering::Greater,
472 (Value::Integer(a), Value::Integer(b)) => a.cmp(b),
474 (&Value::Integer(a), &Value::Number(b)) => cmp_num(a as Number, b),
475 (&Value::Number(a), &Value::Integer(b)) => cmp_num(a, b as Number),
476 (&Value::Number(a), &Value::Number(b)) => cmp_num(a, b),
477 (Value::Integer(_) | Value::Number(_), _) => Ordering::Less,
478 (_, Value::Integer(_) | Value::Number(_)) => Ordering::Greater,
479 (Value::String(a), Value::String(b)) => a.as_bytes().cmp(b.as_bytes()),
481 (Value::String(_), _) => Ordering::Less,
482 (_, Value::String(_)) => Ordering::Greater,
483 (a, b) => a.to_pointer().cmp(&b.to_pointer()),
485 }
486 }
487
488 pub(crate) fn fmt_pretty(
489 &self,
490 fmt: &mut fmt::Formatter,
491 recursive: bool,
492 ident: usize,
493 visited: &mut HashSet<*const c_void>,
494 ) -> fmt::Result {
495 match self {
496 Value::Nil => write!(fmt, "nil"),
497 Value::Boolean(b) => write!(fmt, "{b}"),
498 Value::LightUserData(ud) if ud.0.is_null() => write!(fmt, "null"),
499 Value::LightUserData(ud) => write!(fmt, "lightuserdata: {:?}", ud.0),
500 Value::Integer(i) => write!(fmt, "{i}"),
501 Value::Number(n) => write!(fmt, "{n}"),
502 #[cfg(feature = "luau")]
503 Value::Vector(v) => write!(fmt, "{v}"),
504 Value::String(s) => write!(fmt, "{s:?}"),
505 Value::Table(t) if recursive && !visited.contains(&t.to_pointer()) => {
506 t.fmt_pretty(fmt, ident, visited)
507 }
508 t @ Value::Table(_) => write!(fmt, "table: {:?}", t.to_pointer()),
509 f @ Value::Function(_) => write!(fmt, "function: {:?}", f.to_pointer()),
510 t @ Value::Thread(_) => write!(fmt, "thread: {:?}", t.to_pointer()),
511 u @ Value::UserData(ud) => {
512 let name = ud.type_name().ok().flatten();
514 let s = name
515 .map(|name| format!("{name}: {:?}", u.to_pointer()))
516 .or_else(|| u.to_string().ok())
517 .unwrap_or_else(|| format!("userdata: {:?}", u.to_pointer()));
518 write!(fmt, "{s}")
519 }
520 Value::Error(e) if recursive => write!(fmt, "{e:?}"),
521 Value::Error(_) => write!(fmt, "error"),
522 }
523 }
524}
525
526impl fmt::Debug for Value<'_> {
527 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
528 if fmt.alternate() {
529 return self.fmt_pretty(fmt, true, 0, &mut HashSet::new());
530 }
531 match self {
532 Value::Nil => write!(fmt, "Nil"),
533 Value::Boolean(b) => write!(fmt, "Boolean({b})"),
534 Value::LightUserData(ud) => write!(fmt, "{ud:?}"),
535 Value::Integer(i) => write!(fmt, "Integer({i})"),
536 Value::Number(n) => write!(fmt, "Number({n})"),
537 #[cfg(feature = "luau")]
538 Value::Vector(v) => write!(fmt, "{v:?}"),
539 Value::String(s) => write!(fmt, "String({s:?})"),
540 Value::Table(t) => write!(fmt, "{t:?}"),
541 Value::Function(f) => write!(fmt, "{f:?}"),
542 Value::Thread(t) => write!(fmt, "{t:?}"),
543 Value::UserData(ud) => write!(fmt, "{ud:?}"),
544 Value::Error(e) => write!(fmt, "Error({e:?})"),
545 }
546 }
547}
548
549impl<'lua> PartialEq for Value<'lua> {
550 fn eq(&self, other: &Self) -> bool {
551 match (self, other) {
552 (Value::Nil, Value::Nil) => true,
553 (Value::Boolean(a), Value::Boolean(b)) => a == b,
554 (Value::LightUserData(a), Value::LightUserData(b)) => a == b,
555 (Value::Integer(a), Value::Integer(b)) => *a == *b,
556 (Value::Integer(a), Value::Number(b)) => *a as Number == *b,
557 (Value::Number(a), Value::Integer(b)) => *a == *b as Number,
558 (Value::Number(a), Value::Number(b)) => *a == *b,
559 #[cfg(feature = "luau")]
560 (Value::Vector(v1), Value::Vector(v2)) => v1 == v2,
561 (Value::String(a), Value::String(b)) => a == b,
562 (Value::Table(a), Value::Table(b)) => a == b,
563 (Value::Function(a), Value::Function(b)) => a == b,
564 (Value::Thread(a), Value::Thread(b)) => a == b,
565 (Value::UserData(a), Value::UserData(b)) => a == b,
566 _ => false,
567 }
568 }
569}
570
571impl<'lua> AsRef<Value<'lua>> for Value<'lua> {
572 #[inline]
573 fn as_ref(&self) -> &Self {
574 self
575 }
576}
577
578#[cfg(feature = "serialize")]
580#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
581pub struct SerializableValue<'a, 'lua> {
582 value: &'a Value<'lua>,
583 options: crate::serde::de::Options,
584 visited: Option<Rc<RefCell<FxHashSet<*const c_void>>>>,
586}
587
588#[cfg(feature = "serialize")]
589impl<'lua> Serialize for Value<'lua> {
590 #[inline]
591 fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
592 SerializableValue::new(self, Default::default(), None).serialize(serializer)
593 }
594}
595
596#[cfg(feature = "serialize")]
597impl<'a, 'lua> SerializableValue<'a, 'lua> {
598 #[inline]
599 pub(crate) fn new(
600 value: &'a Value<'lua>,
601 options: crate::serde::de::Options,
602 visited: Option<&Rc<RefCell<FxHashSet<*const c_void>>>>,
603 ) -> Self {
604 if let Value::Table(_) = value {
605 return Self {
606 value,
607 options,
608 visited: visited.cloned().or_else(|| Some(Default::default())),
610 };
611 }
612 Self {
613 value,
614 options,
615 visited: None,
616 }
617 }
618
619 #[must_use]
625 pub const fn deny_unsupported_types(mut self, enabled: bool) -> Self {
626 self.options.deny_unsupported_types = enabled;
627 self
628 }
629
630 #[must_use]
636 pub const fn deny_recursive_tables(mut self, enabled: bool) -> Self {
637 self.options.deny_recursive_tables = enabled;
638 self
639 }
640
641 #[must_use]
645 pub const fn sort_keys(mut self, enabled: bool) -> Self {
646 self.options.sort_keys = enabled;
647 self
648 }
649}
650
651#[cfg(feature = "serialize")]
652impl<'a, 'lua> Serialize for SerializableValue<'a, 'lua> {
653 fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
654 where
655 S: Serializer,
656 {
657 match self.value {
658 Value::Nil => serializer.serialize_unit(),
659 Value::Boolean(b) => serializer.serialize_bool(*b),
660 #[allow(clippy::useless_conversion)]
661 Value::Integer(i) => serializer.serialize_i64((*i).into()),
662 Value::Number(n) => serializer.serialize_f64(*n),
663 #[cfg(feature = "luau")]
664 Value::Vector(v) => v.serialize(serializer),
665 Value::String(s) => s.serialize(serializer),
666 Value::Table(t) => {
667 let visited = self.visited.as_ref().unwrap().clone();
668 SerializableTable::new(t, self.options, visited).serialize(serializer)
669 }
670 Value::LightUserData(ud) if ud.0.is_null() => serializer.serialize_none(),
671 Value::UserData(ud) if ud.is_serializable() || self.options.deny_unsupported_types => {
672 ud.serialize(serializer)
673 }
674 Value::Function(_)
675 | Value::Thread(_)
676 | Value::UserData(_)
677 | Value::LightUserData(_)
678 | Value::Error(_) => {
679 if self.options.deny_unsupported_types {
680 let msg = format!("cannot serialize <{}>", self.value.type_name());
681 Err(ser::Error::custom(msg))
682 } else {
683 serializer.serialize_unit()
684 }
685 }
686 }
687 }
688}
689
690pub trait IntoLua<'lua>: Sized {
692 fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>>;
694
695 #[doc(hidden)]
700 #[inline]
701 unsafe fn push_into_stack(self, lua: &'lua Lua) -> Result<()> {
702 lua.push_value(self.into_lua(lua)?)
703 }
704}
705
706pub trait FromLua<'lua>: Sized {
708 fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> Result<Self>;
710
711 #[doc(hidden)]
716 #[inline]
717 fn from_lua_arg(arg: Value<'lua>, i: usize, to: Option<&str>, lua: &'lua Lua) -> Result<Self> {
718 Self::from_lua(arg, lua).map_err(|err| Error::BadArgument {
719 to: to.map(|s| s.to_string()),
720 pos: i,
721 name: None,
722 cause: Arc::new(err),
723 })
724 }
725
726 #[doc(hidden)]
728 #[inline]
729 unsafe fn from_stack(idx: c_int, lua: &'lua Lua) -> Result<Self> {
730 Self::from_lua(lua.stack_value(idx), lua)
731 }
732
733 #[doc(hidden)]
735 #[inline]
736 unsafe fn from_stack_arg(
737 idx: c_int,
738 i: usize,
739 to: Option<&str>,
740 lua: &'lua Lua,
741 ) -> Result<Self> {
742 Self::from_stack(idx, lua).map_err(|err| Error::BadArgument {
743 to: to.map(|s| s.to_string()),
744 pos: i,
745 name: None,
746 cause: Arc::new(err),
747 })
748 }
749}
750
751#[derive(Debug, Clone)]
753pub struct MultiValue<'lua> {
754 vec: Vec<Value<'lua>>,
755 lua: Option<&'lua Lua>,
756}
757
758impl Drop for MultiValue<'_> {
759 fn drop(&mut self) {
760 if let Some(lua) = self.lua {
761 let vec = mem::take(&mut self.vec);
762 lua.push_multivalue_to_pool(vec);
763 }
764 }
765}
766
767impl<'lua> MultiValue<'lua> {
768 pub const fn new() -> MultiValue<'lua> {
770 MultiValue {
771 vec: Vec::new(),
772 lua: None,
773 }
774 }
775
776 #[inline]
778 pub(crate) fn with_lua_and_capacity(lua: &'lua Lua, capacity: usize) -> MultiValue<'lua> {
779 let vec = lua
780 .pop_multivalue_from_pool()
781 .map(|mut vec| {
782 vec.reserve(capacity);
783 vec
784 })
785 .unwrap_or_else(|| Vec::with_capacity(capacity));
786 MultiValue {
787 vec,
788 lua: Some(lua),
789 }
790 }
791}
792
793impl<'lua> Default for MultiValue<'lua> {
794 #[inline]
795 fn default() -> MultiValue<'lua> {
796 MultiValue::new()
797 }
798}
799
800impl<'lua> FromIterator<Value<'lua>> for MultiValue<'lua> {
801 #[inline]
802 fn from_iter<I: IntoIterator<Item = Value<'lua>>>(iter: I) -> Self {
803 MultiValue::from_vec(Vec::from_iter(iter))
804 }
805}
806
807impl<'lua> IntoIterator for MultiValue<'lua> {
808 type Item = Value<'lua>;
809 type IntoIter = iter::Rev<vec::IntoIter<Value<'lua>>>;
810
811 #[inline]
812 fn into_iter(mut self) -> Self::IntoIter {
813 let vec = mem::take(&mut self.vec);
814 mem::forget(self);
815 vec.into_iter().rev()
816 }
817}
818
819impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
820 type Item = &'a Value<'lua>;
821 type IntoIter = iter::Rev<slice::Iter<'a, Value<'lua>>>;
822
823 #[inline]
824 fn into_iter(self) -> Self::IntoIter {
825 self.vec.iter().rev()
826 }
827}
828
829impl<'lua> Index<usize> for MultiValue<'lua> {
830 type Output = Value<'lua>;
831
832 #[inline]
833 fn index(&self, index: usize) -> &Self::Output {
834 if let Some(result) = self.get(index) {
835 result
836 } else {
837 panic!(
838 "index out of bounds: the len is {} but the index is {}",
839 self.len(),
840 index
841 )
842 }
843 }
844}
845
846impl<'lua> MultiValue<'lua> {
847 #[inline]
848 pub fn from_vec(mut vec: Vec<Value<'lua>>) -> MultiValue<'lua> {
849 vec.reverse();
850 MultiValue { vec, lua: None }
851 }
852
853 #[inline]
854 pub fn into_vec(mut self) -> Vec<Value<'lua>> {
855 let mut vec = mem::take(&mut self.vec);
856 mem::forget(self);
857 vec.reverse();
858 vec
859 }
860
861 #[inline]
862 pub fn get(&self, index: usize) -> Option<&Value<'lua>> {
863 if index < self.vec.len() {
864 return self.vec.get(self.vec.len() - index - 1);
865 }
866 None
867 }
868
869 #[inline]
870 pub fn pop_front(&mut self) -> Option<Value<'lua>> {
871 self.vec.pop()
872 }
873
874 #[inline]
875 pub fn push_front(&mut self, value: Value<'lua>) {
876 self.vec.push(value);
877 }
878
879 #[inline]
880 pub fn clear(&mut self) {
881 self.vec.clear();
882 }
883
884 #[inline]
885 pub fn len(&self) -> usize {
886 self.vec.len()
887 }
888
889 #[inline]
890 pub fn is_empty(&self) -> bool {
891 self.vec.is_empty()
892 }
893
894 #[inline]
895 pub fn iter(&self) -> iter::Rev<slice::Iter<Value<'lua>>> {
896 self.vec.iter().rev()
897 }
898
899 #[inline]
900 pub(crate) fn drain_all(&mut self) -> iter::Rev<vec::Drain<Value<'lua>>> {
901 self.vec.drain(..).rev()
902 }
903
904 #[inline]
905 pub(crate) fn refill(
906 &mut self,
907 iter: impl IntoIterator<Item = Result<Value<'lua>>>,
908 ) -> Result<()> {
909 self.vec.clear();
910 for value in iter {
911 self.vec.push(value?);
912 }
913 self.vec.reverse();
914 Ok(())
915 }
916}
917
918pub trait IntoLuaMulti<'lua>: Sized {
923 fn into_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>>;
925
926 #[doc(hidden)]
930 #[inline]
931 unsafe fn push_into_stack_multi(self, lua: &'lua Lua) -> Result<c_int> {
932 let mut values = self.into_lua_multi(lua)?;
933 let len: c_int = values.len().try_into().unwrap();
934 unsafe {
935 check_stack(lua.state(), len + 1)?;
936 for v in values.drain_all() {
937 lua.push_value(v)?;
938 }
939 }
940 Ok(len)
941 }
942}
943
944pub trait FromLuaMulti<'lua>: Sized {
949 fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
956
957 #[doc(hidden)]
962 #[inline]
963 fn from_lua_args(
964 args: MultiValue<'lua>,
965 i: usize,
966 to: Option<&str>,
967 lua: &'lua Lua,
968 ) -> Result<Self> {
969 let _ = (i, to);
970 Self::from_lua_multi(args, lua)
971 }
972
973 #[doc(hidden)]
975 #[inline]
976 unsafe fn from_stack_multi(nvals: c_int, lua: &'lua Lua) -> Result<Self> {
977 let mut values = MultiValue::with_lua_and_capacity(lua, nvals as usize);
978 for idx in 1..=nvals {
979 values.push_front(lua.stack_value(-idx));
980 }
981 if nvals > 0 {
982 ffi::lua_pop(lua.state(), nvals);
984 }
985 Self::from_lua_multi(values, lua)
986 }
987
988 #[doc(hidden)]
990 #[inline]
991 unsafe fn from_stack_args(
992 nargs: c_int,
993 i: usize,
994 to: Option<&str>,
995 lua: &'lua Lua,
996 ) -> Result<Self> {
997 let _ = (i, to);
998 Self::from_stack_multi(nargs, lua)
999 }
1000}
1001
1002#[cfg(test)]
1003mod assertions {
1004 use super::*;
1005
1006 static_assertions::assert_not_impl_any!(Value: Send);
1007 static_assertions::assert_not_impl_any!(MultiValue: Send);
1008}