1use std::borrow::Cow;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::ffi::{CStr, CString};
4use std::hash::{BuildHasher, Hash};
5use std::os::raw::c_int;
6use std::string::String as StdString;
7use std::{slice, str};
8
9use bstr::{BStr, BString};
10use num_traits::cast;
11
12use crate::error::{Error, Result};
13use crate::function::Function;
14use crate::state::{Lua, RawLua};
15use crate::string::String;
16use crate::table::Table;
17use crate::thread::Thread;
18use crate::types::{LightUserData, MaybeSend, RegistryKey};
19use crate::userdata::{AnyUserData, UserData};
20use crate::value::{FromLua, IntoLua, Nil, Value};
21
22impl IntoLua for Value {
23 #[inline]
24 fn into_lua(self, _: &Lua) -> Result<Value> {
25 Ok(self)
26 }
27}
28
29impl IntoLua for &Value {
30 #[inline]
31 fn into_lua(self, _: &Lua) -> Result<Value> {
32 Ok(self.clone())
33 }
34
35 #[inline]
36 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
37 lua.push_value(self)
38 }
39}
40
41impl FromLua for Value {
42 #[inline]
43 fn from_lua(lua_value: Value, _: &Lua) -> Result<Self> {
44 Ok(lua_value)
45 }
46}
47
48impl IntoLua for String {
49 #[inline]
50 fn into_lua(self, _: &Lua) -> Result<Value> {
51 Ok(Value::String(self))
52 }
53}
54
55impl IntoLua for &String {
56 #[inline]
57 fn into_lua(self, _: &Lua) -> Result<Value> {
58 Ok(Value::String(self.clone()))
59 }
60
61 #[inline]
62 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
63 lua.push_ref(&self.0);
64 Ok(())
65 }
66}
67
68impl FromLua for String {
69 #[inline]
70 fn from_lua(value: Value, lua: &Lua) -> Result<String> {
71 let ty = value.type_name();
72 lua.coerce_string(value)?
73 .ok_or_else(|| Error::FromLuaConversionError {
74 from: ty,
75 to: "string",
76 message: Some("expected string or number".to_string()),
77 })
78 }
79
80 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
81 let state = lua.state();
82 let type_id = ffi::lua_type(state, idx);
83 if type_id == ffi::LUA_TSTRING {
84 ffi::lua_xpush(state, lua.ref_thread(), idx);
85 return Ok(String(lua.pop_ref_thread()));
86 }
87 Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
89 }
90}
91
92impl IntoLua for Table {
93 #[inline]
94 fn into_lua(self, _: &Lua) -> Result<Value> {
95 Ok(Value::Table(self))
96 }
97}
98
99impl IntoLua for &Table {
100 #[inline]
101 fn into_lua(self, _: &Lua) -> Result<Value> {
102 Ok(Value::Table(self.clone()))
103 }
104
105 #[inline]
106 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
107 lua.push_ref(&self.0);
108 Ok(())
109 }
110}
111
112impl FromLua for Table {
113 #[inline]
114 fn from_lua(value: Value, _: &Lua) -> Result<Table> {
115 match value {
116 Value::Table(table) => Ok(table),
117 _ => Err(Error::FromLuaConversionError {
118 from: value.type_name(),
119 to: "table",
120 message: None,
121 }),
122 }
123 }
124}
125
126impl IntoLua for Function {
127 #[inline]
128 fn into_lua(self, _: &Lua) -> Result<Value> {
129 Ok(Value::Function(self))
130 }
131}
132
133impl IntoLua for &Function {
134 #[inline]
135 fn into_lua(self, _: &Lua) -> Result<Value> {
136 Ok(Value::Function(self.clone()))
137 }
138
139 #[inline]
140 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
141 lua.push_ref(&self.0);
142 Ok(())
143 }
144}
145
146impl FromLua for Function {
147 #[inline]
148 fn from_lua(value: Value, _: &Lua) -> Result<Function> {
149 match value {
150 Value::Function(table) => Ok(table),
151 _ => Err(Error::FromLuaConversionError {
152 from: value.type_name(),
153 to: "function",
154 message: None,
155 }),
156 }
157 }
158}
159
160impl IntoLua for Thread {
161 #[inline]
162 fn into_lua(self, _: &Lua) -> Result<Value> {
163 Ok(Value::Thread(self))
164 }
165}
166
167impl IntoLua for &Thread {
168 #[inline]
169 fn into_lua(self, _: &Lua) -> Result<Value> {
170 Ok(Value::Thread(self.clone()))
171 }
172
173 #[inline]
174 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
175 lua.push_ref(&self.0);
176 Ok(())
177 }
178}
179
180impl FromLua for Thread {
181 #[inline]
182 fn from_lua(value: Value, _: &Lua) -> Result<Thread> {
183 match value {
184 Value::Thread(t) => Ok(t),
185 _ => Err(Error::FromLuaConversionError {
186 from: value.type_name(),
187 to: "thread",
188 message: None,
189 }),
190 }
191 }
192}
193
194impl IntoLua for AnyUserData {
195 #[inline]
196 fn into_lua(self, _: &Lua) -> Result<Value> {
197 Ok(Value::UserData(self))
198 }
199}
200
201impl IntoLua for &AnyUserData {
202 #[inline]
203 fn into_lua(self, _: &Lua) -> Result<Value> {
204 Ok(Value::UserData(self.clone()))
205 }
206
207 #[inline]
208 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
209 lua.push_ref(&self.0);
210 Ok(())
211 }
212}
213
214impl FromLua for AnyUserData {
215 #[inline]
216 fn from_lua(value: Value, _: &Lua) -> Result<AnyUserData> {
217 match value {
218 Value::UserData(ud) => Ok(ud),
219 _ => Err(Error::FromLuaConversionError {
220 from: value.type_name(),
221 to: "userdata",
222 message: None,
223 }),
224 }
225 }
226}
227
228impl<T: UserData + MaybeSend + 'static> IntoLua for T {
229 #[inline]
230 fn into_lua(self, lua: &Lua) -> Result<Value> {
231 Ok(Value::UserData(lua.create_userdata(self)?))
232 }
233}
234
235impl IntoLua for Error {
236 #[inline]
237 fn into_lua(self, _: &Lua) -> Result<Value> {
238 Ok(Value::Error(Box::new(self)))
239 }
240}
241
242impl FromLua for Error {
243 #[inline]
244 fn from_lua(value: Value, lua: &Lua) -> Result<Error> {
245 match value {
246 Value::Error(err) => Ok(*err),
247 val => Ok(Error::runtime(
248 lua.coerce_string(val)?
249 .and_then(|s| Some(s.to_str().ok()?.to_owned()))
250 .unwrap_or_else(|| "<unprintable error>".to_owned()),
251 )),
252 }
253 }
254}
255
256impl IntoLua for RegistryKey {
257 #[inline]
258 fn into_lua(self, lua: &Lua) -> Result<Value> {
259 lua.registry_value(&self)
260 }
261
262 #[inline]
263 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
264 <&RegistryKey>::push_into_stack(&self, lua)
265 }
266}
267
268impl IntoLua for &RegistryKey {
269 #[inline]
270 fn into_lua(self, lua: &Lua) -> Result<Value> {
271 lua.registry_value(self)
272 }
273
274 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
275 if !lua.owns_registry_value(self) {
276 return Err(Error::MismatchedRegistryKey);
277 }
278
279 match self.id() {
280 ffi::LUA_REFNIL => ffi::lua_pushnil(lua.state()),
281 id => {
282 ffi::lua_rawgeti(lua.state(), ffi::LUA_REGISTRYINDEX, id as _);
283 }
284 }
285 Ok(())
286 }
287}
288
289impl FromLua for RegistryKey {
290 #[inline]
291 fn from_lua(value: Value, lua: &Lua) -> Result<RegistryKey> {
292 lua.create_registry_value(value)
293 }
294}
295
296impl IntoLua for bool {
297 #[inline]
298 fn into_lua(self, _: &Lua) -> Result<Value> {
299 Ok(Value::Boolean(self))
300 }
301
302 #[inline]
303 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
304 ffi::lua_pushboolean(lua.state(), self as c_int);
305 Ok(())
306 }
307}
308
309impl FromLua for bool {
310 #[inline]
311 fn from_lua(v: Value, _: &Lua) -> Result<Self> {
312 match v {
313 Value::Nil => Ok(false),
314 Value::Boolean(b) => Ok(b),
315 _ => Ok(true),
316 }
317 }
318
319 #[inline]
320 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
321 Ok(ffi::lua_toboolean(lua.state(), idx) != 0)
322 }
323}
324
325impl IntoLua for LightUserData {
326 #[inline]
327 fn into_lua(self, _: &Lua) -> Result<Value> {
328 Ok(Value::LightUserData(self))
329 }
330}
331
332impl FromLua for LightUserData {
333 #[inline]
334 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
335 match value {
336 Value::LightUserData(ud) => Ok(ud),
337 _ => Err(Error::FromLuaConversionError {
338 from: value.type_name(),
339 to: "light userdata",
340 message: None,
341 }),
342 }
343 }
344}
345
346#[cfg(feature = "luau")]
347impl IntoLua for crate::types::Vector {
348 #[inline]
349 fn into_lua(self, _: &Lua) -> Result<Value> {
350 Ok(Value::Vector(self))
351 }
352}
353
354#[cfg(feature = "luau")]
355impl FromLua for crate::types::Vector {
356 #[inline]
357 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
358 match value {
359 Value::Vector(v) => Ok(v),
360 _ => Err(Error::FromLuaConversionError {
361 from: value.type_name(),
362 to: "vector",
363 message: None,
364 }),
365 }
366 }
367}
368
369impl IntoLua for StdString {
370 #[inline]
371 fn into_lua(self, lua: &Lua) -> Result<Value> {
372 Ok(Value::String(lua.create_string(self)?))
373 }
374
375 #[inline]
376 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
377 push_bytes_into_stack(self, lua)
378 }
379}
380
381impl FromLua for StdString {
382 #[inline]
383 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
384 let ty = value.type_name();
385 Ok(lua
386 .coerce_string(value)?
387 .ok_or_else(|| Error::FromLuaConversionError {
388 from: ty,
389 to: "String",
390 message: Some("expected string or number".to_string()),
391 })?
392 .to_str()?
393 .to_owned())
394 }
395
396 #[inline]
397 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
398 let state = lua.state();
399 let type_id = ffi::lua_type(state, idx);
400 if type_id == ffi::LUA_TSTRING {
401 let mut size = 0;
402 let data = ffi::lua_tolstring(state, idx, &mut size);
403 let bytes = slice::from_raw_parts(data as *const u8, size);
404 return str::from_utf8(bytes)
405 .map(|s| s.to_owned())
406 .map_err(|e| Error::FromLuaConversionError {
407 from: "string",
408 to: "String",
409 message: Some(e.to_string()),
410 });
411 }
412 Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
414 }
415}
416
417impl IntoLua for &str {
418 #[inline]
419 fn into_lua(self, lua: &Lua) -> Result<Value> {
420 Ok(Value::String(lua.create_string(self)?))
421 }
422
423 #[inline]
424 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
425 push_bytes_into_stack(self, lua)
426 }
427}
428
429impl IntoLua for Cow<'_, str> {
430 #[inline]
431 fn into_lua(self, lua: &Lua) -> Result<Value> {
432 Ok(Value::String(lua.create_string(self.as_bytes())?))
433 }
434}
435
436impl IntoLua for Box<str> {
437 #[inline]
438 fn into_lua(self, lua: &Lua) -> Result<Value> {
439 Ok(Value::String(lua.create_string(&*self)?))
440 }
441}
442
443impl FromLua for Box<str> {
444 #[inline]
445 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
446 let ty = value.type_name();
447 Ok(lua
448 .coerce_string(value)?
449 .ok_or_else(|| Error::FromLuaConversionError {
450 from: ty,
451 to: "Box<str>",
452 message: Some("expected string or number".to_string()),
453 })?
454 .to_str()?
455 .to_owned()
456 .into_boxed_str())
457 }
458}
459
460impl IntoLua for CString {
461 #[inline]
462 fn into_lua(self, lua: &Lua) -> Result<Value> {
463 Ok(Value::String(lua.create_string(self.as_bytes())?))
464 }
465}
466
467impl FromLua for CString {
468 #[inline]
469 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
470 let ty = value.type_name();
471 let string = lua
472 .coerce_string(value)?
473 .ok_or_else(|| Error::FromLuaConversionError {
474 from: ty,
475 to: "CString",
476 message: Some("expected string or number".to_string()),
477 })?;
478
479 match CStr::from_bytes_with_nul(&string.as_bytes_with_nul()) {
480 Ok(s) => Ok(s.into()),
481 Err(_) => Err(Error::FromLuaConversionError {
482 from: ty,
483 to: "CString",
484 message: Some("invalid C-style string".to_string()),
485 }),
486 }
487 }
488}
489
490impl IntoLua for &CStr {
491 #[inline]
492 fn into_lua(self, lua: &Lua) -> Result<Value> {
493 Ok(Value::String(lua.create_string(self.to_bytes())?))
494 }
495}
496
497impl IntoLua for Cow<'_, CStr> {
498 #[inline]
499 fn into_lua(self, lua: &Lua) -> Result<Value> {
500 Ok(Value::String(lua.create_string(self.to_bytes())?))
501 }
502}
503
504impl IntoLua for BString {
505 #[inline]
506 fn into_lua(self, lua: &Lua) -> Result<Value> {
507 Ok(Value::String(lua.create_string(self)?))
508 }
509}
510
511impl FromLua for BString {
512 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
513 let ty = value.type_name();
514 match value {
515 Value::String(s) => Ok((*s.as_bytes()).into()),
516 #[cfg(feature = "luau")]
517 Value::UserData(ud) if ud.1 == crate::types::SubtypeId::Buffer => unsafe {
518 let lua = ud.0.lua.lock();
519 let mut size = 0usize;
520 let buf = ffi::lua_tobuffer(lua.ref_thread(), ud.0.index, &mut size);
521 mlua_assert!(!buf.is_null(), "invalid Luau buffer");
522 Ok(slice::from_raw_parts(buf as *const u8, size).into())
523 },
524 _ => Ok((*lua
525 .coerce_string(value)?
526 .ok_or_else(|| Error::FromLuaConversionError {
527 from: ty,
528 to: "BString",
529 message: Some("expected string or number".to_string()),
530 })?
531 .as_bytes())
532 .into()),
533 }
534 }
535
536 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
537 let state = lua.state();
538 match ffi::lua_type(state, idx) {
539 ffi::LUA_TSTRING => {
540 let mut size = 0;
541 let data = ffi::lua_tolstring(state, idx, &mut size);
542 Ok(slice::from_raw_parts(data as *const u8, size).into())
543 }
544 #[cfg(feature = "luau")]
545 ffi::LUA_TBUFFER => {
546 let mut size = 0;
547 let buf = ffi::lua_tobuffer(state, idx, &mut size);
548 mlua_assert!(!buf.is_null(), "invalid Luau buffer");
549 Ok(slice::from_raw_parts(buf as *const u8, size).into())
550 }
551 type_id => {
552 Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
554 }
555 }
556 }
557}
558
559impl IntoLua for &BStr {
560 #[inline]
561 fn into_lua(self, lua: &Lua) -> Result<Value> {
562 Ok(Value::String(lua.create_string(self)?))
563 }
564}
565
566#[inline]
567unsafe fn push_bytes_into_stack<T>(this: T, lua: &RawLua) -> Result<()>
568where
569 T: IntoLua + AsRef<[u8]>,
570{
571 let bytes = this.as_ref();
572 if lua.unlikely_memory_error() && bytes.len() < (1 << 30) {
573 ffi::lua_pushlstring(lua.state(), bytes.as_ptr() as *const _, bytes.len());
575 return Ok(());
576 }
577 lua.push_value(&T::into_lua(this, lua.lua())?)
579}
580
581macro_rules! lua_convert_int {
582 ($x:ty) => {
583 impl IntoLua for $x {
584 #[inline]
585 fn into_lua(self, _: &Lua) -> Result<Value> {
586 cast(self)
587 .map(Value::Integer)
588 .or_else(|| cast(self).map(Value::Number))
589 .ok_or_else(|| Error::ToLuaConversionError {
591 from: stringify!($x),
592 to: "number",
593 message: Some("out of range".to_owned()),
594 })
595 }
596
597 #[inline]
598 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
599 match cast(self) {
600 Some(i) => ffi::lua_pushinteger(lua.state(), i),
601 None => ffi::lua_pushnumber(lua.state(), self as ffi::lua_Number),
602 }
603 Ok(())
604 }
605 }
606
607 impl FromLua for $x {
608 #[inline]
609 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
610 let ty = value.type_name();
611 (match value {
612 Value::Integer(i) => cast(i),
613 Value::Number(n) => cast(n),
614 _ => {
615 if let Some(i) = lua.coerce_integer(value.clone())? {
616 cast(i)
617 } else {
618 cast(
619 lua.coerce_number(value)?
620 .ok_or_else(|| Error::FromLuaConversionError {
621 from: ty,
622 to: stringify!($x),
623 message: Some(
624 "expected number or string coercible to number".to_string(),
625 ),
626 })?,
627 )
628 }
629 }
630 })
631 .ok_or_else(|| Error::FromLuaConversionError {
632 from: ty,
633 to: stringify!($x),
634 message: Some("out of range".to_owned()),
635 })
636 }
637
638 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
639 let state = lua.state();
640 let type_id = ffi::lua_type(state, idx);
641 if type_id == ffi::LUA_TNUMBER {
642 let mut ok = 0;
643 let i = ffi::lua_tointegerx(state, idx, &mut ok);
644 if ok != 0 {
645 return cast(i).ok_or_else(|| Error::FromLuaConversionError {
646 from: "integer",
647 to: stringify!($x),
648 message: Some("out of range".to_owned()),
649 });
650 }
651 }
652 Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
654 }
655 }
656 };
657}
658
659lua_convert_int!(i8);
660lua_convert_int!(u8);
661lua_convert_int!(i16);
662lua_convert_int!(u16);
663lua_convert_int!(i32);
664lua_convert_int!(u32);
665lua_convert_int!(i64);
666lua_convert_int!(u64);
667lua_convert_int!(i128);
668lua_convert_int!(u128);
669lua_convert_int!(isize);
670lua_convert_int!(usize);
671
672macro_rules! lua_convert_float {
673 ($x:ty) => {
674 impl IntoLua for $x {
675 #[inline]
676 fn into_lua(self, _: &Lua) -> Result<Value> {
677 cast(self)
678 .ok_or_else(|| Error::ToLuaConversionError {
679 from: stringify!($x),
680 to: "number",
681 message: Some("out of range".to_string()),
682 })
683 .map(Value::Number)
684 }
685 }
686
687 impl FromLua for $x {
688 #[inline]
689 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
690 let ty = value.type_name();
691 lua.coerce_number(value)?
692 .ok_or_else(|| Error::FromLuaConversionError {
693 from: ty,
694 to: stringify!($x),
695 message: Some("expected number or string coercible to number".to_string()),
696 })
697 .and_then(|n| {
698 cast(n).ok_or_else(|| Error::FromLuaConversionError {
699 from: ty,
700 to: stringify!($x),
701 message: Some("number out of range".to_string()),
702 })
703 })
704 }
705
706 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
707 let state = lua.state();
708 let type_id = ffi::lua_type(state, idx);
709 if type_id == ffi::LUA_TNUMBER {
710 let mut ok = 0;
711 let i = ffi::lua_tonumberx(state, idx, &mut ok);
712 if ok != 0 {
713 return cast(i).ok_or_else(|| Error::FromLuaConversionError {
714 from: "number",
715 to: stringify!($x),
716 message: Some("out of range".to_owned()),
717 });
718 }
719 }
720 Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua())
722 }
723 }
724 };
725}
726
727lua_convert_float!(f32);
728lua_convert_float!(f64);
729
730impl<T> IntoLua for &[T]
731where
732 T: IntoLua + Clone,
733{
734 #[inline]
735 fn into_lua(self, lua: &Lua) -> Result<Value> {
736 Ok(Value::Table(lua.create_sequence_from(self.iter().cloned())?))
737 }
738}
739
740impl<T, const N: usize> IntoLua for [T; N]
741where
742 T: IntoLua,
743{
744 #[inline]
745 fn into_lua(self, lua: &Lua) -> Result<Value> {
746 Ok(Value::Table(lua.create_sequence_from(self)?))
747 }
748}
749
750impl<T, const N: usize> FromLua for [T; N]
751where
752 T: FromLua,
753{
754 #[inline]
755 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
756 match value {
757 #[cfg(feature = "luau")]
758 #[rustfmt::skip]
759 Value::Vector(v) if N == crate::types::Vector::SIZE => unsafe {
760 use std::{mem, ptr};
761 let mut arr: [mem::MaybeUninit<T>; N] = mem::MaybeUninit::uninit().assume_init();
762 ptr::write(arr[0].as_mut_ptr() , T::from_lua(Value::Number(v.x() as _), _lua)?);
763 ptr::write(arr[1].as_mut_ptr(), T::from_lua(Value::Number(v.y() as _), _lua)?);
764 ptr::write(arr[2].as_mut_ptr(), T::from_lua(Value::Number(v.z() as _), _lua)?);
765 #[cfg(feature = "luau-vector4")]
766 ptr::write(arr[3].as_mut_ptr(), T::from_lua(Value::Number(v.w() as _), _lua)?);
767 Ok(mem::transmute_copy(&arr))
768 },
769 Value::Table(table) => {
770 let vec = table.sequence_values().collect::<Result<Vec<_>>>()?;
771 vec.try_into()
772 .map_err(|vec: Vec<T>| Error::FromLuaConversionError {
773 from: "table",
774 to: "Array",
775 message: Some(format!("expected table of length {}, got {}", N, vec.len())),
776 })
777 }
778 _ => Err(Error::FromLuaConversionError {
779 from: value.type_name(),
780 to: "Array",
781 message: Some("expected table".to_string()),
782 }),
783 }
784 }
785}
786
787impl<T: IntoLua> IntoLua for Box<[T]> {
788 #[inline]
789 fn into_lua(self, lua: &Lua) -> Result<Value> {
790 Ok(Value::Table(lua.create_sequence_from(self.into_vec())?))
791 }
792}
793
794impl<T: FromLua> FromLua for Box<[T]> {
795 #[inline]
796 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
797 Ok(Vec::<T>::from_lua(value, lua)?.into_boxed_slice())
798 }
799}
800
801impl<T: IntoLua> IntoLua for Vec<T> {
802 #[inline]
803 fn into_lua(self, lua: &Lua) -> Result<Value> {
804 Ok(Value::Table(lua.create_sequence_from(self)?))
805 }
806}
807
808impl<T: FromLua> FromLua for Vec<T> {
809 #[inline]
810 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
811 match value {
812 Value::Table(table) => table.sequence_values().collect(),
813 _ => Err(Error::FromLuaConversionError {
814 from: value.type_name(),
815 to: "Vec",
816 message: Some("expected table".to_string()),
817 }),
818 }
819 }
820}
821
822impl<K: Eq + Hash + IntoLua, V: IntoLua, S: BuildHasher> IntoLua for HashMap<K, V, S> {
823 #[inline]
824 fn into_lua(self, lua: &Lua) -> Result<Value> {
825 Ok(Value::Table(lua.create_table_from(self)?))
826 }
827}
828
829impl<K: Eq + Hash + FromLua, V: FromLua, S: BuildHasher + Default> FromLua for HashMap<K, V, S> {
830 #[inline]
831 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
832 if let Value::Table(table) = value {
833 table.pairs().collect()
834 } else {
835 Err(Error::FromLuaConversionError {
836 from: value.type_name(),
837 to: "HashMap",
838 message: Some("expected table".to_string()),
839 })
840 }
841 }
842}
843
844impl<K: Ord + IntoLua, V: IntoLua> IntoLua for BTreeMap<K, V> {
845 #[inline]
846 fn into_lua(self, lua: &Lua) -> Result<Value> {
847 Ok(Value::Table(lua.create_table_from(self)?))
848 }
849}
850
851impl<K: Ord + FromLua, V: FromLua> FromLua for BTreeMap<K, V> {
852 #[inline]
853 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
854 if let Value::Table(table) = value {
855 table.pairs().collect()
856 } else {
857 Err(Error::FromLuaConversionError {
858 from: value.type_name(),
859 to: "BTreeMap",
860 message: Some("expected table".to_string()),
861 })
862 }
863 }
864}
865
866impl<T: Eq + Hash + IntoLua, S: BuildHasher> IntoLua for HashSet<T, S> {
867 #[inline]
868 fn into_lua(self, lua: &Lua) -> Result<Value> {
869 Ok(Value::Table(
870 lua.create_table_from(self.into_iter().map(|val| (val, true)))?,
871 ))
872 }
873}
874
875impl<T: Eq + Hash + FromLua, S: BuildHasher + Default> FromLua for HashSet<T, S> {
876 #[inline]
877 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
878 match value {
879 Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
880 Value::Table(table) => table.pairs::<T, Value>().map(|res| res.map(|(k, _)| k)).collect(),
881 _ => Err(Error::FromLuaConversionError {
882 from: value.type_name(),
883 to: "HashSet",
884 message: Some("expected table".to_string()),
885 }),
886 }
887 }
888}
889
890impl<T: Ord + IntoLua> IntoLua for BTreeSet<T> {
891 #[inline]
892 fn into_lua(self, lua: &Lua) -> Result<Value> {
893 Ok(Value::Table(
894 lua.create_table_from(self.into_iter().map(|val| (val, true)))?,
895 ))
896 }
897}
898
899impl<T: Ord + FromLua> FromLua for BTreeSet<T> {
900 #[inline]
901 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
902 match value {
903 Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
904 Value::Table(table) => table.pairs::<T, Value>().map(|res| res.map(|(k, _)| k)).collect(),
905 _ => Err(Error::FromLuaConversionError {
906 from: value.type_name(),
907 to: "BTreeSet",
908 message: Some("expected table".to_string()),
909 }),
910 }
911 }
912}
913
914impl<T: IntoLua> IntoLua for Option<T> {
915 #[inline]
916 fn into_lua(self, lua: &Lua) -> Result<Value> {
917 match self {
918 Some(val) => val.into_lua(lua),
919 None => Ok(Nil),
920 }
921 }
922
923 #[inline]
924 unsafe fn push_into_stack(self, lua: &RawLua) -> Result<()> {
925 match self {
926 Some(val) => val.push_into_stack(lua)?,
927 None => ffi::lua_pushnil(lua.state()),
928 }
929 Ok(())
930 }
931}
932
933impl<T: FromLua> FromLua for Option<T> {
934 #[inline]
935 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
936 match value {
937 Nil => Ok(None),
938 value => Ok(Some(T::from_lua(value, lua)?)),
939 }
940 }
941
942 #[inline]
943 unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result<Self> {
944 match ffi::lua_type(lua.state(), idx) {
945 ffi::LUA_TNIL => Ok(None),
946 _ => Ok(Some(T::from_stack(idx, lua)?)),
947 }
948 }
949}