1use crate::error::{Error, Result};
5use crate::function::Function;
6use crate::multi::{MultiValue, Variadic};
7use crate::state::Lua;
8use crate::string::LuaString;
9use crate::table::Table;
10use crate::traits::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti};
11use crate::value::{Integer, Number, Value};
12
13impl IntoLua for Value {
18 fn into_lua(self, _lua: &Lua) -> Result<Value> {
19 Ok(self)
20 }
21}
22
23impl FromLua for Value {
24 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
25 Ok(value)
26 }
27}
28
29impl IntoLuaMulti for () {
40 fn into_lua_multi(self, _lua: &Lua) -> Result<MultiValue> {
41 Ok(MultiValue::new())
42 }
43}
44
45impl FromLuaMulti for () {
46 fn from_lua_multi(_values: MultiValue, _lua: &Lua) -> Result<Self> {
47 Ok(())
48 }
49}
50
51impl IntoLua for bool {
56 fn into_lua(self, _lua: &Lua) -> Result<Value> {
57 Ok(Value::Boolean(self))
58 }
59}
60
61impl FromLua for bool {
62 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
63 Ok(match value {
65 Value::Nil => false,
66 Value::Boolean(b) => b,
67 _ => true,
68 })
69 }
70}
71
72macro_rules! impl_integer {
77 ($($ty:ty),*) => {$(
78 impl IntoLua for $ty {
79 fn into_lua(self, _lua: &Lua) -> Result<Value> {
80 let as_i64 = i64::try_from(self).map_err(|_| Error::ToLuaConversionError {
81 from: stringify!($ty),
82 to: "integer",
83 message: Some("value out of i64 range".to_string()),
84 })?;
85 Ok(Value::Integer(as_i64))
86 }
87 }
88
89 impl FromLua for $ty {
90 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
91 fn from_float(f: f64) -> Result<$ty> {
96 let t = f.trunc();
101 if t < (i128::MIN as f64) || t > (i128::MAX as f64) {
102 return Err(Error::FromLuaConversionError {
103 from: "number",
104 to: stringify!($ty).to_string(),
105 message: Some("out of range".to_string()),
106 });
107 }
108 let wide = t as i128;
109 <$ty>::try_from(wide).map_err(|_| Error::FromLuaConversionError {
110 from: "number",
111 to: stringify!($ty).to_string(),
112 message: Some("out of range".to_string()),
113 })
114 }
115 match value {
116 Value::Integer(i) => {
117 <$ty>::try_from(i).map_err(|_| Error::FromLuaConversionError {
118 from: "number",
119 to: stringify!($ty).to_string(),
120 message: Some("out of range".to_string()),
121 })
122 }
123 Value::Number(f) => {
124 if !f.is_finite() {
129 return Err(Error::FromLuaConversionError {
130 from: "number",
131 to: stringify!($ty).to_string(),
132 message: Some("number has no integer representation".to_string()),
133 });
134 }
135 from_float(f)
136 }
137 Value::String(ref s) => {
140 let text = s.to_string_lossy();
141 let trimmed = text.trim();
142 if let Ok(i) = trimmed.parse::<i64>() {
143 <$ty>::try_from(i).map_err(|_| Error::FromLuaConversionError {
144 from: "string",
145 to: stringify!($ty).to_string(),
146 message: Some("out of range".to_string()),
147 })
148 } else if let Ok(f) = trimmed.parse::<f64>() {
149 if !f.is_finite() {
150 return Err(Error::FromLuaConversionError {
151 from: "string",
152 to: stringify!($ty).to_string(),
153 message: Some("number has no integer representation".to_string()),
154 });
155 }
156 from_float(f)
157 } else {
158 Err(Error::FromLuaConversionError {
159 from: "string",
160 to: stringify!($ty).to_string(),
161 message: Some("not a number".to_string()),
162 })
163 }
164 }
165 other => {
166 Err(Error::FromLuaConversionError {
167 from: other.type_name(),
168 to: stringify!($ty).to_string(),
169 message: None,
170 })
171 }
172 }
173 }
174 }
175 )*};
176}
177
178impl_integer!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
179
180macro_rules! impl_integer_128 {
184 ($($ty:ty),*) => {$(
185 impl IntoLua for $ty {
186 fn into_lua(self, _lua: &Lua) -> Result<Value> {
187 Ok(Value::Number(self as f64))
188 }
189 }
190
191 impl FromLua for $ty {
192 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
193 let n: f64 = match value {
194 Value::Integer(i) => i as f64,
195 Value::Number(f) => f,
196 Value::String(ref s) => {
197 s.to_string_lossy().trim().parse::<f64>().map_err(|_| {
198 Error::FromLuaConversionError {
199 from: "string",
200 to: stringify!($ty).to_string(),
201 message: Some("not a number".to_string()),
202 }
203 })?
204 }
205 other => {
206 return Err(Error::FromLuaConversionError {
207 from: other.type_name(),
208 to: stringify!($ty).to_string(),
209 message: None,
210 });
211 }
212 };
213 if n.fract() != 0.0 || !n.is_finite() {
214 return Err(Error::FromLuaConversionError {
215 from: "number",
216 to: stringify!($ty).to_string(),
217 message: Some("number has no integer representation".to_string()),
218 });
219 }
220 Ok(n as $ty)
221 }
222 }
223 )*};
224}
225
226impl_integer_128!(i128, u128);
227
228const _: () = {
230 fn _assert(_x: Integer) -> i64 {
232 _x
233 }
234};
235
236impl IntoLua for f64 {
241 fn into_lua(self, _lua: &Lua) -> Result<Value> {
242 Ok(Value::Number(self))
243 }
244}
245
246impl FromLua for f64 {
247 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
248 match value {
249 Value::Number(n) => Ok(n),
250 Value::Integer(i) => Ok(i as f64),
251 Value::String(ref s) => {
253 let text = s.to_string_lossy();
254 text.trim()
255 .parse::<f64>()
256 .map_err(|_| Error::FromLuaConversionError {
257 from: "string",
258 to: "f64".to_string(),
259 message: Some("not a number".to_string()),
260 })
261 }
262 other => Err(Error::FromLuaConversionError {
263 from: other.type_name(),
264 to: "f64".to_string(),
265 message: None,
266 }),
267 }
268 }
269}
270
271impl IntoLua for f32 {
272 fn into_lua(self, _lua: &Lua) -> Result<Value> {
273 Ok(Value::Number(self as Number))
274 }
275}
276
277impl FromLua for f32 {
278 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
279 Ok(f64::from_lua(value, lua)? as f32)
280 }
281}
282
283impl IntoLua for String {
288 fn into_lua(self, lua: &Lua) -> Result<Value> {
289 Ok(Value::String(lua.create_string(&self)))
290 }
291}
292
293impl IntoLua for &str {
294 fn into_lua(self, lua: &Lua) -> Result<Value> {
295 Ok(Value::String(lua.create_string(self)))
296 }
297}
298
299impl IntoLua for &String {
300 fn into_lua(self, lua: &Lua) -> Result<Value> {
301 Ok(Value::String(lua.create_string(self)))
302 }
303}
304
305impl FromLua for String {
306 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
307 match value {
308 Value::String(s) => s.to_str(),
309 Value::Integer(i) => Ok(i.to_string()),
311 Value::Number(n) => Ok(n.to_string()),
312 other => Err(Error::FromLuaConversionError {
313 from: other.type_name(),
314 to: "String".to_string(),
315 message: None,
316 }),
317 }
318 }
319}
320
321impl IntoLua for LuaString {
322 fn into_lua(self, _lua: &Lua) -> Result<Value> {
323 Ok(Value::String(self))
324 }
325}
326
327impl IntoLua for &LuaString {
328 fn into_lua(self, _lua: &Lua) -> Result<Value> {
329 Ok(Value::String(self.clone()))
330 }
331}
332
333impl FromLua for LuaString {
334 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
335 match value {
336 Value::String(s) => Ok(s),
337 Value::Integer(i) => Ok(_lua.create_string(i.to_string())),
338 Value::Number(n) => Ok(_lua.create_string(n.to_string())),
339 other => Err(Error::FromLuaConversionError {
340 from: other.type_name(),
341 to: "String".to_string(),
342 message: None,
343 }),
344 }
345 }
346}
347
348impl IntoLua for Table {
353 fn into_lua(self, _lua: &Lua) -> Result<Value> {
354 Ok(Value::Table(self))
355 }
356}
357
358impl IntoLua for &Table {
359 fn into_lua(self, _lua: &Lua) -> Result<Value> {
360 Ok(Value::Table(self.clone()))
361 }
362}
363
364impl FromLua for Table {
365 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
366 match value {
367 Value::Table(t) => Ok(t),
368 other => Err(Error::FromLuaConversionError {
369 from: other.type_name(),
370 to: "Table".to_string(),
371 message: None,
372 }),
373 }
374 }
375}
376
377impl IntoLua for Function {
378 fn into_lua(self, _lua: &Lua) -> Result<Value> {
379 Ok(Value::Function(self))
380 }
381}
382
383impl IntoLua for &Function {
384 fn into_lua(self, _lua: &Lua) -> Result<Value> {
385 Ok(Value::Function(self.clone()))
386 }
387}
388
389impl FromLua for Function {
390 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
391 match value {
392 Value::Function(f) => Ok(f),
393 other => Err(Error::FromLuaConversionError {
394 from: other.type_name(),
395 to: "Function".to_string(),
396 message: None,
397 }),
398 }
399 }
400}
401
402impl IntoLua for crate::Vector {
407 fn into_lua(self, _lua: &Lua) -> Result<Value> {
408 Ok(Value::Vector(self))
409 }
410}
411
412impl FromLua for crate::Vector {
413 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
414 match value {
415 Value::Vector(v) => Ok(v),
416 other => Err(Error::FromLuaConversionError {
417 from: other.type_name(),
418 to: "vector".to_string(),
419 message: None,
420 }),
421 }
422 }
423}
424
425impl IntoLua for crate::Buffer {
430 fn into_lua(self, _lua: &Lua) -> Result<Value> {
431 Ok(Value::Buffer(self))
432 }
433}
434
435impl IntoLua for &crate::Buffer {
436 fn into_lua(self, _lua: &Lua) -> Result<Value> {
437 Ok(Value::Buffer(self.clone()))
438 }
439}
440
441impl FromLua for crate::Buffer {
442 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
443 match value {
444 Value::Buffer(buf) => Ok(buf),
445 other => Err(Error::FromLuaConversionError {
446 from: other.type_name(),
447 to: "buffer".to_string(),
448 message: None,
449 }),
450 }
451 }
452}
453
454impl<T: IntoLua> IntoLua for Option<T> {
459 fn into_lua(self, lua: &Lua) -> Result<Value> {
460 match self {
461 Some(v) => v.into_lua(lua),
462 None => Ok(Value::Nil),
463 }
464 }
465}
466
467impl<T: FromLua> FromLua for Option<T> {
468 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
469 match value {
470 Value::Nil => Ok(None),
471 other => Ok(Some(T::from_lua(other, lua)?)),
472 }
473 }
474}
475
476impl<T: IntoLua> IntoLua for Vec<T> {
481 fn into_lua(self, lua: &Lua) -> Result<Value> {
482 let table = lua.create_table();
483 for (i, item) in self.into_iter().enumerate() {
484 table.set((i + 1) as i64, item)?;
486 }
487 Ok(Value::Table(table))
488 }
489}
490
491impl<T: IntoLua + Clone> IntoLua for &[T] {
492 fn into_lua(self, lua: &Lua) -> Result<Value> {
493 let table = lua.create_table();
494 for (i, item) in self.iter().enumerate() {
495 table.raw_set((i + 1) as i64, item.clone())?;
496 }
497 Ok(Value::Table(table))
498 }
499}
500
501impl<T: FromLua> FromLua for Vec<T> {
502 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
503 match value {
504 Value::Table(t) => {
505 let len = t.raw_len();
506 let mut out = Vec::with_capacity(len);
507 for i in 1..=len {
508 out.push(t.raw_get::<T>(i as i64)?);
509 }
510 Ok(out)
511 }
512 other => Err(Error::FromLuaConversionError {
513 from: other.type_name(),
514 to: "Vec".to_string(),
515 message: None,
516 }),
517 }
518 }
519}
520
521impl<T: IntoLua, const N: usize> IntoLua for [T; N] {
526 fn into_lua(self, lua: &Lua) -> Result<Value> {
527 let table = lua.create_table();
528 for (i, item) in self.into_iter().enumerate() {
529 table.raw_set((i + 1) as i64, item)?;
530 }
531 Ok(Value::Table(table))
532 }
533}
534
535impl<T: FromLua, const N: usize> FromLua for [T; N] {
536 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
537 if let Value::Vector(v) = value {
540 if N == crate::Vector::SIZE {
541 let x = T::from_lua(Value::Number(v.x() as f64), lua)?;
542 let y = T::from_lua(Value::Number(v.y() as f64), lua)?;
543 let z = T::from_lua(Value::Number(v.z() as f64), lua)?;
544 let comps = vec![x, y, z];
545 return <[T; N]>::try_from(comps).map_err(|_| Error::FromLuaConversionError {
546 from: "vector",
547 to: format!("[T; {N}]"),
548 message: None,
549 });
550 }
551 return Err(Error::FromLuaConversionError {
552 from: "vector",
553 to: format!("[T; {N}]"),
554 message: Some(format!(
555 "expected array of length {}, got {N}",
556 crate::Vector::SIZE
557 )),
558 });
559 }
560 let vec: Vec<T> = Vec::from_lua(value, lua)?;
561 let len = vec.len();
562 <[T; N]>::try_from(vec).map_err(|_| Error::FromLuaConversionError {
563 from: "table",
564 to: format!("[T; {N}]"),
565 message: Some(format!("expected table of length {N}, got {len}")),
566 })
567 }
568}
569
570use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
575use std::hash::Hash;
576
577impl<K: IntoLua + Eq + Hash, V: IntoLua, S: std::hash::BuildHasher> IntoLua for HashMap<K, V, S> {
578 fn into_lua(self, lua: &Lua) -> Result<Value> {
579 let table = lua.create_table();
580 for (k, v) in self {
581 table.raw_set(k, v)?;
582 }
583 Ok(Value::Table(table))
584 }
585}
586
587impl<K: FromLua + Eq + Hash, V: FromLua, S: std::hash::BuildHasher + Default> FromLua
588 for HashMap<K, V, S>
589{
590 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
591 match value {
592 Value::Table(t) => {
593 let mut out = HashMap::with_hasher(S::default());
594 for pair in t.pairs::<K, V>() {
595 let (k, v) = pair?;
596 out.insert(k, v);
597 }
598 Ok(out)
599 }
600 other => Err(Error::FromLuaConversionError {
601 from: other.type_name(),
602 to: "HashMap".to_string(),
603 message: None,
604 }),
605 }
606 }
607}
608
609impl<K: IntoLua + Ord, V: IntoLua> IntoLua for BTreeMap<K, V> {
610 fn into_lua(self, lua: &Lua) -> Result<Value> {
611 let table = lua.create_table();
612 for (k, v) in self {
613 table.raw_set(k, v)?;
614 }
615 Ok(Value::Table(table))
616 }
617}
618
619impl<K: FromLua + Ord, V: FromLua> FromLua for BTreeMap<K, V> {
620 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
621 match value {
622 Value::Table(t) => {
623 let mut out = BTreeMap::new();
624 for pair in t.pairs::<K, V>() {
625 let (k, v) = pair?;
626 out.insert(k, v);
627 }
628 Ok(out)
629 }
630 other => Err(Error::FromLuaConversionError {
631 from: other.type_name(),
632 to: "BTreeMap".to_string(),
633 message: None,
634 }),
635 }
636 }
637}
638
639impl<T: IntoLua + Eq + Hash, S: std::hash::BuildHasher> IntoLua for HashSet<T, S> {
644 fn into_lua(self, lua: &Lua) -> Result<Value> {
645 let table = lua.create_table();
646 for item in self {
647 table.raw_set(item, true)?;
648 }
649 Ok(Value::Table(table))
650 }
651}
652
653impl<T: FromLua + Eq + Hash, S: std::hash::BuildHasher + Default> FromLua for HashSet<T, S> {
654 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
655 from_lua_set(value, lua, "HashSet", |it| {
656 let mut out = HashSet::with_hasher(S::default());
657 for v in it {
658 out.insert(v?);
659 }
660 Ok(out)
661 })
662 }
663}
664
665impl<T: IntoLua + Ord> IntoLua for BTreeSet<T> {
666 fn into_lua(self, lua: &Lua) -> Result<Value> {
667 let table = lua.create_table();
668 for item in self {
669 table.raw_set(item, true)?;
670 }
671 Ok(Value::Table(table))
672 }
673}
674
675impl<T: FromLua + Ord> FromLua for BTreeSet<T> {
676 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
677 from_lua_set(value, lua, "BTreeSet", |it| {
678 let mut out = BTreeSet::new();
679 for v in it {
680 out.insert(v?);
681 }
682 Ok(out)
683 })
684 }
685}
686
687fn from_lua_set<T: FromLua, C>(
692 value: Value,
693 _lua: &Lua,
694 to: &'static str,
695 build: impl FnOnce(SetIter<T>) -> Result<C>,
696) -> Result<C> {
697 match value {
698 Value::Table(t) => {
699 if t.raw_len() > 0 {
700 build(SetIter::Seq(t.sequence_values::<T>()))
701 } else {
702 let keys: Vec<Result<T>> =
703 t.pairs::<T, Value>().map(|p| p.map(|(k, _)| k)).collect();
704 build(SetIter::Keys(keys.into_iter()))
705 }
706 }
707 other => Err(Error::FromLuaConversionError {
708 from: other.type_name(),
709 to: to.to_string(),
710 message: None,
711 }),
712 }
713}
714
715enum SetIter<T: FromLua> {
716 Seq(crate::table::TableSequence<T>),
717 Keys(std::vec::IntoIter<Result<T>>),
718}
719
720impl<T: FromLua> Iterator for SetIter<T> {
721 type Item = Result<T>;
722 fn next(&mut self) -> Option<Self::Item> {
723 match self {
724 SetIter::Seq(s) => s.next(),
725 SetIter::Keys(k) => k.next(),
726 }
727 }
728}
729
730impl IntoLua for char {
735 fn into_lua(self, lua: &Lua) -> Result<Value> {
736 Ok(Value::String(lua.create_string(self.to_string())))
737 }
738}
739
740impl FromLua for char {
741 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
742 match value {
743 Value::String(_) | Value::Integer(_) | Value::Number(_) => {}
744 other => {
745 return Err(Error::FromLuaConversionError {
746 from: other.type_name(),
747 to: "char".to_string(),
748 message: Some("expected string or integer".to_string()),
749 })
750 }
751 }
752 if let Value::Integer(_) | Value::Number(_) = value {
753 let i = i64::from_lua(value, lua)?;
754 let cp = u32::try_from(i).ok().and_then(char::from_u32);
755 return cp.ok_or(Error::FromLuaConversionError {
756 from: "number",
757 to: "char".to_string(),
758 message: Some("integer out of range for a unicode char".to_string()),
759 });
760 }
761 let s = String::from_lua(value, lua)?;
762 let mut chars = s.chars();
763 match (chars.next(), chars.next()) {
764 (Some(c), None) => Ok(c),
765 _ => Err(Error::FromLuaConversionError {
766 from: "string",
767 to: "char".to_string(),
768 message: Some("expected string to have exactly one char".to_string()),
769 }),
770 }
771 }
772}
773
774impl IntoLua for std::borrow::Cow<'_, str> {
779 fn into_lua(self, lua: &Lua) -> Result<Value> {
780 Ok(Value::String(lua.create_string(self.as_ref())))
781 }
782}
783
784impl IntoLua for Box<str> {
785 fn into_lua(self, lua: &Lua) -> Result<Value> {
786 Ok(Value::String(lua.create_string(&*self)))
787 }
788}
789
790impl FromLua for Box<str> {
791 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
792 Ok(String::from_lua(value, lua)?.into_boxed_str())
793 }
794}
795
796impl IntoLua for std::ffi::CString {
797 fn into_lua(self, lua: &Lua) -> Result<Value> {
798 Ok(Value::String(lua.create_string(self.as_bytes())))
799 }
800}
801
802impl FromLua for std::ffi::CString {
803 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
804 let bytes = match value {
805 Value::String(s) => s.as_bytes(),
806 other => {
807 return Err(Error::FromLuaConversionError {
808 from: other.type_name(),
809 to: "CString".to_string(),
810 message: None,
811 })
812 }
813 };
814 std::ffi::CString::new(bytes).map_err(|e| Error::FromLuaConversionError {
815 from: "string",
816 to: "CString".to_string(),
817 message: Some(format!("interior nul byte: {e}")),
818 })
819 }
820}
821
822impl<T: IntoLua> IntoLua for Box<[T]> {
823 fn into_lua(self, lua: &Lua) -> Result<Value> {
824 self.into_vec().into_lua(lua)
825 }
826}
827
828impl<T: FromLua> FromLua for Box<[T]> {
829 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
830 Ok(Vec::<T>::from_lua(value, lua)?.into_boxed_slice())
831 }
832}
833
834impl<T: IntoLua> IntoLuaMulti for Variadic<T> {
839 fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
840 let vec: Vec<T> = self.into();
841 let mut m = MultiValue::with_capacity(vec.len());
842 for item in vec {
843 m.push_back(item.into_lua(lua)?);
844 }
845 Ok(m)
846 }
847}
848
849impl<T: FromLua> FromLuaMulti for Variadic<T> {
850 fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self> {
851 let mut out = Vec::with_capacity(values.len());
852 for v in values {
853 out.push(T::from_lua(v, lua)?);
854 }
855 Ok(Variadic::from(out))
856 }
857}
858
859impl IntoLua for crate::light_userdata::LightUserData {
864 fn into_lua(self, _lua: &Lua) -> Result<Value> {
865 Ok(Value::LightUserData(self))
866 }
867}
868
869impl FromLua for crate::light_userdata::LightUserData {
870 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
871 match value {
872 Value::LightUserData(lud) => Ok(lud),
873 other => Err(Error::FromLuaConversionError {
874 from: other.type_name(),
875 to: "LightUserData".to_string(),
876 message: None,
877 }),
878 }
879 }
880}
881
882impl IntoLua for Error {
883 fn into_lua(self, _lua: &Lua) -> Result<Value> {
884 Ok(Value::Error(Box::new(self)))
885 }
886}
887
888impl FromLua for Error {
889 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
890 Ok(match value {
891 Value::Error(e) => *e,
892 Value::String(s) => Error::RuntimeError(s.to_string_lossy()),
895 other => Error::RuntimeError(other.to_string().unwrap_or_default()),
896 })
897 }
898}
899
900impl<T: IntoLuaMulti, E: IntoLua> IntoLuaMulti for std::result::Result<T, E> {
903 fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
904 match self {
905 Ok(v) => v.into_lua_multi(lua),
906 Err(e) => {
907 let mut m = MultiValue::with_capacity(2);
908 m.push_back(Value::Nil);
909 m.push_back(e.into_lua(lua)?);
910 Ok(m)
911 }
912 }
913 }
914}
915
916impl IntoLuaMulti for MultiValue {
921 fn into_lua_multi(self, _lua: &Lua) -> Result<MultiValue> {
922 Ok(self)
923 }
924}
925
926impl FromLuaMulti for MultiValue {
927 fn from_lua_multi(values: MultiValue, _lua: &Lua) -> Result<Self> {
928 Ok(values)
929 }
930}
931
932macro_rules! impl_tuple_into {
939 () => {};
940 ($first:ident $($rest:ident)*) => {
941 impl_tuple_into!($($rest)*);
942
943 #[allow(non_snake_case)]
944 impl<$first: IntoLuaMulti, $($rest: IntoLuaMulti,)*> IntoLuaMulti for ($first, $($rest,)*) {
945 fn into_lua_multi(self, lua: &Lua) -> Result<MultiValue> {
946 let ($first, $($rest,)*) = self;
947 let mut m = MultiValue::new();
948 for v in $first.into_lua_multi(lua)? { m.push_back(v); }
949 $( for v in $rest.into_lua_multi(lua)? { m.push_back(v); } )*
950 Ok(m)
951 }
952 }
953 };
954}
955
956impl_tuple_into!(A B C D E F G H I J K L);
957
958macro_rules! impl_tuple_from {
967 ($last:ident;) => {
969 #[allow(non_snake_case)]
970 impl<$last: FromLuaMulti> FromLuaMulti for ($last,) {
971 fn from_lua_multi(values: MultiValue, lua: &Lua) -> Result<Self> {
972 Ok(($last::from_lua_multi(values, lua)?,))
973 }
974 }
975 };
976 ($last:ident; $head0:ident $($head:ident)*) => {
977 impl_tuple_from!($last; $($head)*);
978
979 #[allow(non_snake_case)]
980 impl<$head0: FromLua, $($head: FromLua,)* $last: FromLuaMulti>
981 FromLuaMulti for ($head0, $($head,)* $last,)
982 {
983 fn from_lua_multi(mut values: MultiValue, lua: &Lua) -> Result<Self> {
984 let $head0 = $head0::from_lua(values.pop_front().unwrap_or(Value::Nil), lua)?;
985 $( let $head = $head::from_lua(values.pop_front().unwrap_or(Value::Nil), lua)?; )*
986 let $last = $last::from_lua_multi(values, lua)?;
987 Ok(($head0, $($head,)* $last,))
988 }
989 }
990 };
991}
992
993impl_tuple_from!(L; A B C D E F G H I J K);