1use std::borrow::Cow;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::ffi::{CStr, CString, OsStr, OsString};
4use std::hash::{BuildHasher, Hash};
5use std::os::raw::c_int;
6use std::path::{Path, PathBuf};
7use std::string::String as StdString;
8use std::{mem, slice, str};
9
10use bstr::{BStr, BString, ByteSlice, ByteVec};
11use num_traits::cast;
12
13use crate::error::{Error, Result};
14use crate::function::Function;
15use crate::state::{Lua, RawLua};
16use crate::string::{BorrowedBytes, BorrowedStr, String};
17use crate::table::Table;
18use crate::thread::Thread;
19use crate::traits::{FromLua, IntoLua, ShortTypeName as _};
20use crate::types::{Either, LightUserData, MaybeSend, RegistryKey};
21use crate::userdata::{AnyUserData, UserData};
22use crate::value::{Nil, Value};
23
24impl IntoLua for Value {
25 #[inline]
26 fn into_lua(self, _: &Lua) -> Result<Value> {
27 Ok(self)
28 }
29}
30
31impl IntoLua for &Value {
32 #[inline]
33 fn into_lua(self, _: &Lua) -> Result<Value> {
34 Ok(self.clone())
35 }
36
37 #[inline]
38 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
39 lua.push_value(self, state)
40 }
41}
42
43impl FromLua for Value {
44 #[inline]
45 fn from_lua(lua_value: Value, _: &Lua) -> Result<Self> {
46 Ok(lua_value)
47 }
48}
49
50impl IntoLua for String {
51 #[inline]
52 fn into_lua(self, _: &Lua) -> Result<Value> {
53 Ok(Value::String(self))
54 }
55}
56
57impl IntoLua for &String {
58 #[inline]
59 fn into_lua(self, _: &Lua) -> Result<Value> {
60 Ok(Value::String(self.clone()))
61 }
62
63 #[inline]
64 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
65 lua.push_ref(&self.0, state);
66 Ok(())
67 }
68}
69
70impl FromLua for String {
71 #[inline]
72 fn from_lua(value: Value, lua: &Lua) -> Result<String> {
73 let ty = value.type_name();
74 lua.coerce_string(value)?
75 .ok_or_else(|| Error::FromLuaConversionError {
76 from: ty,
77 to: "string".to_string(),
78 message: Some("expected string or number".to_string()),
79 })
80 }
81
82 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
83 let type_id = ffi::lua_type(state, idx);
84 if type_id == ffi::LUA_TSTRING {
85 ffi::lua_xpush(state, lua.ref_thread(), idx);
86 return Ok(String(lua.pop_ref_thread()));
87 }
88 Self::from_lua(lua.stack_value(idx, Some(type_id), state), lua.lua())
90 }
91}
92
93impl IntoLua for BorrowedStr<'_> {
94 #[inline]
95 fn into_lua(self, _: &Lua) -> Result<Value> {
96 Ok(Value::String(self.borrow.into_owned()))
97 }
98
99 #[inline]
100 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
101 lua.push_ref(&self.borrow.0, state);
102 Ok(())
103 }
104}
105
106impl IntoLua for &BorrowedStr<'_> {
107 #[inline]
108 fn into_lua(self, _: &Lua) -> Result<Value> {
109 Ok(Value::String(self.borrow.clone().into_owned()))
110 }
111
112 #[inline]
113 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
114 lua.push_ref(&self.borrow.0, state);
115 Ok(())
116 }
117}
118
119impl FromLua for BorrowedStr<'_> {
120 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
121 let s = String::from_lua(value, lua)?;
122 let BorrowedStr { buf, _lua, .. } = BorrowedStr::try_from(&s)?;
123 let buf = unsafe { mem::transmute::<&str, &'static str>(buf) };
124 let borrow = Cow::Owned(s);
125 Ok(Self { buf, borrow, _lua })
126 }
127
128 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
129 let s = String::from_stack(idx, lua, state)?;
130 let BorrowedStr { buf, _lua, .. } = BorrowedStr::try_from(&s)?;
131 let buf = unsafe { mem::transmute::<&str, &'static str>(buf) };
132 let borrow = Cow::Owned(s);
133 Ok(Self { buf, borrow, _lua })
134 }
135}
136
137impl IntoLua for BorrowedBytes<'_> {
138 #[inline]
139 fn into_lua(self, _: &Lua) -> Result<Value> {
140 Ok(Value::String(self.borrow.into_owned()))
141 }
142
143 #[inline]
144 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
145 lua.push_ref(&self.borrow.0, state);
146 Ok(())
147 }
148}
149
150impl IntoLua for &BorrowedBytes<'_> {
151 #[inline]
152 fn into_lua(self, _: &Lua) -> Result<Value> {
153 Ok(Value::String(self.borrow.clone().into_owned()))
154 }
155
156 #[inline]
157 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
158 lua.push_ref(&self.borrow.0, state);
159 Ok(())
160 }
161}
162
163impl FromLua for BorrowedBytes<'_> {
164 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
165 let s = String::from_lua(value, lua)?;
166 let BorrowedBytes { buf, _lua, .. } = BorrowedBytes::from(&s);
167 let buf = unsafe { mem::transmute::<&[u8], &'static [u8]>(buf) };
168 let borrow = Cow::Owned(s);
169 Ok(Self { buf, borrow, _lua })
170 }
171
172 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
173 let s = String::from_stack(idx, lua, state)?;
174 let BorrowedBytes { buf, _lua, .. } = BorrowedBytes::from(&s);
175 let buf = unsafe { mem::transmute::<&[u8], &'static [u8]>(buf) };
176 let borrow = Cow::Owned(s);
177 Ok(Self { buf, borrow, _lua })
178 }
179}
180
181impl IntoLua for Table {
182 #[inline]
183 fn into_lua(self, _: &Lua) -> Result<Value> {
184 Ok(Value::Table(self))
185 }
186}
187
188impl IntoLua for &Table {
189 #[inline]
190 fn into_lua(self, _: &Lua) -> Result<Value> {
191 Ok(Value::Table(self.clone()))
192 }
193
194 #[inline]
195 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
196 lua.push_ref(&self.0, state);
197 Ok(())
198 }
199}
200
201impl FromLua for Table {
202 #[inline]
203 fn from_lua(value: Value, _: &Lua) -> Result<Table> {
204 match value {
205 Value::Table(table) => Ok(table),
206 _ => Err(Error::FromLuaConversionError {
207 from: value.type_name(),
208 to: "table".to_string(),
209 message: None,
210 }),
211 }
212 }
213}
214
215impl IntoLua for Function {
216 #[inline]
217 fn into_lua(self, _: &Lua) -> Result<Value> {
218 Ok(Value::Function(self))
219 }
220}
221
222impl IntoLua for &Function {
223 #[inline]
224 fn into_lua(self, _: &Lua) -> Result<Value> {
225 Ok(Value::Function(self.clone()))
226 }
227
228 #[inline]
229 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
230 lua.push_ref(&self.0, state);
231 Ok(())
232 }
233}
234
235impl FromLua for Function {
236 #[inline]
237 fn from_lua(value: Value, _: &Lua) -> Result<Function> {
238 match value {
239 Value::Function(table) => Ok(table),
240 _ => Err(Error::FromLuaConversionError {
241 from: value.type_name(),
242 to: "function".to_string(),
243 message: None,
244 }),
245 }
246 }
247}
248
249impl IntoLua for Thread {
250 #[inline]
251 fn into_lua(self, _: &Lua) -> Result<Value> {
252 Ok(Value::Thread(self))
253 }
254}
255
256impl IntoLua for &Thread {
257 #[inline]
258 fn into_lua(self, _: &Lua) -> Result<Value> {
259 Ok(Value::Thread(self.clone()))
260 }
261
262 #[inline]
263 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
264 lua.push_ref(&self.0, state);
265 Ok(())
266 }
267}
268
269impl FromLua for Thread {
270 #[inline]
271 fn from_lua(value: Value, _: &Lua) -> Result<Thread> {
272 match value {
273 Value::Thread(t) => Ok(t),
274 _ => Err(Error::FromLuaConversionError {
275 from: value.type_name(),
276 to: "thread".to_string(),
277 message: None,
278 }),
279 }
280 }
281}
282
283impl IntoLua for AnyUserData {
284 #[inline]
285 fn into_lua(self, _: &Lua) -> Result<Value> {
286 Ok(Value::UserData(self))
287 }
288}
289
290impl IntoLua for &AnyUserData {
291 #[inline]
292 fn into_lua(self, _: &Lua) -> Result<Value> {
293 Ok(Value::UserData(self.clone()))
294 }
295
296 #[inline]
297 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
298 lua.push_ref(&self.0, state);
299 Ok(())
300 }
301}
302
303impl FromLua for AnyUserData {
304 #[inline]
305 fn from_lua(value: Value, _: &Lua) -> Result<AnyUserData> {
306 match value {
307 Value::UserData(ud) => Ok(ud),
308 _ => Err(Error::FromLuaConversionError {
309 from: value.type_name(),
310 to: "userdata".to_string(),
311 message: None,
312 }),
313 }
314 }
315}
316
317impl<T: UserData + MaybeSend + 'static> IntoLua for T {
318 #[inline]
319 fn into_lua(self, lua: &Lua) -> Result<Value> {
320 Ok(Value::UserData(lua.create_userdata(self)?))
321 }
322}
323
324impl IntoLua for Error {
325 #[inline]
326 fn into_lua(self, _: &Lua) -> Result<Value> {
327 Ok(Value::Error(Box::new(self)))
328 }
329}
330
331impl FromLua for Error {
332 #[inline]
333 fn from_lua(value: Value, _: &Lua) -> Result<Error> {
334 match value {
335 Value::Error(err) => Ok(*err),
336 val => Ok(Error::runtime(val.to_string()?)),
337 }
338 }
339}
340
341#[cfg(feature = "anyhow")]
342impl IntoLua for anyhow::Error {
343 #[inline]
344 fn into_lua(self, _: &Lua) -> Result<Value> {
345 Ok(Value::Error(Box::new(Error::from(self))))
346 }
347}
348
349impl IntoLua for RegistryKey {
350 #[inline]
351 fn into_lua(self, lua: &Lua) -> Result<Value> {
352 lua.registry_value(&self)
353 }
354
355 #[inline]
356 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
357 <&RegistryKey>::push_into_stack(&self, lua, state)
358 }
359}
360
361impl IntoLua for &RegistryKey {
362 #[inline]
363 fn into_lua(self, lua: &Lua) -> Result<Value> {
364 lua.registry_value(self)
365 }
366
367 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
368 if !lua.owns_registry_value(self) {
369 return Err(Error::MismatchedRegistryKey);
370 }
371
372 match self.id() {
373 ffi::LUA_REFNIL => ffi::lua_pushnil(state),
374 id => {
375 ffi::lua_rawgeti(state, ffi::LUA_REGISTRYINDEX, id as _);
376 }
377 }
378 Ok(())
379 }
380}
381
382impl FromLua for RegistryKey {
383 #[inline]
384 fn from_lua(value: Value, lua: &Lua) -> Result<RegistryKey> {
385 lua.create_registry_value(value)
386 }
387}
388
389impl IntoLua for bool {
390 #[inline]
391 fn into_lua(self, _: &Lua) -> Result<Value> {
392 Ok(Value::Boolean(self))
393 }
394
395 #[inline]
396 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
397 ffi::lua_pushboolean(state, self as c_int);
398 Ok(())
399 }
400}
401
402impl FromLua for bool {
403 #[inline]
404 fn from_lua(v: Value, _: &Lua) -> Result<Self> {
405 match v {
406 Value::Nil => Ok(false),
407 Value::Boolean(b) => Ok(b),
408 _ => Ok(true),
409 }
410 }
411
412 #[inline]
413 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
414 Ok(ffi::lua_toboolean(state, idx) != 0)
415 }
416}
417
418impl IntoLua for LightUserData {
419 #[inline]
420 fn into_lua(self, _: &Lua) -> Result<Value> {
421 Ok(Value::LightUserData(self))
422 }
423}
424
425impl FromLua for LightUserData {
426 #[inline]
427 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
428 match value {
429 Value::LightUserData(ud) => Ok(ud),
430 _ => Err(Error::FromLuaConversionError {
431 from: value.type_name(),
432 to: "lightuserdata".to_string(),
433 message: None,
434 }),
435 }
436 }
437}
438
439impl IntoLua for crate::Vector {
440 #[inline]
441 fn into_lua(self, _: &Lua) -> Result<Value> {
442 Ok(Value::Vector(self))
443 }
444}
445
446impl FromLua for crate::Vector {
447 #[inline]
448 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
449 match value {
450 Value::Vector(v) => Ok(v),
451 _ => Err(Error::FromLuaConversionError {
452 from: value.type_name(),
453 to: "vector".to_string(),
454 message: None,
455 }),
456 }
457 }
458}
459
460impl IntoLua for crate::Buffer {
461 #[inline]
462 fn into_lua(self, _: &Lua) -> Result<Value> {
463 Ok(Value::Buffer(self))
464 }
465}
466
467impl IntoLua for &crate::Buffer {
468 #[inline]
469 fn into_lua(self, _: &Lua) -> Result<Value> {
470 Ok(Value::Buffer(self.clone()))
471 }
472
473 #[inline]
474 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
475 lua.push_ref(&self.0, state);
476 Ok(())
477 }
478}
479
480impl FromLua for crate::Buffer {
481 #[inline]
482 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
483 match value {
484 Value::Buffer(buf) => Ok(buf),
485 _ => Err(Error::FromLuaConversionError {
486 from: value.type_name(),
487 to: "buffer".to_string(),
488 message: None,
489 }),
490 }
491 }
492}
493
494impl IntoLua for StdString {
495 #[inline]
496 fn into_lua(self, lua: &Lua) -> Result<Value> {
497 Ok(Value::String(lua.create_string(self)?))
498 }
499
500 #[inline]
501 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
502 push_bytes_into_stack(self, lua, state)
503 }
504}
505
506impl FromLua for StdString {
507 #[inline]
508 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
509 let ty = value.type_name();
510 Ok(lua
511 .coerce_string(value)?
512 .ok_or_else(|| Error::FromLuaConversionError {
513 from: ty,
514 to: Self::type_name(),
515 message: Some("expected string or number".to_string()),
516 })?
517 .to_str()?
518 .to_owned())
519 }
520
521 #[inline]
522 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
523 let type_id = ffi::lua_type(state, idx);
524 if type_id == ffi::LUA_TSTRING {
525 let mut size = 0;
526 let data = ffi::lua_tolstring(state, idx, &mut size);
527 let bytes = slice::from_raw_parts(data as *const u8, size);
528 return str::from_utf8(bytes)
529 .map(|s| s.to_owned())
530 .map_err(|e| Error::FromLuaConversionError {
531 from: "string",
532 to: Self::type_name(),
533 message: Some(e.to_string()),
534 });
535 }
536 Self::from_lua(lua.stack_value(idx, Some(type_id), state), lua.lua())
538 }
539}
540
541impl IntoLua for &str {
542 #[inline]
543 fn into_lua(self, lua: &Lua) -> Result<Value> {
544 Ok(Value::String(lua.create_string(self)?))
545 }
546
547 #[inline]
548 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
549 push_bytes_into_stack(self, lua, state)
550 }
551}
552
553impl IntoLua for Cow<'_, str> {
554 #[inline]
555 fn into_lua(self, lua: &Lua) -> Result<Value> {
556 Ok(Value::String(lua.create_string(self.as_bytes())?))
557 }
558}
559
560impl IntoLua for Box<str> {
561 #[inline]
562 fn into_lua(self, lua: &Lua) -> Result<Value> {
563 Ok(Value::String(lua.create_string(&*self)?))
564 }
565}
566
567impl FromLua for Box<str> {
568 #[inline]
569 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
570 let ty = value.type_name();
571 Ok(lua
572 .coerce_string(value)?
573 .ok_or_else(|| Error::FromLuaConversionError {
574 from: ty,
575 to: Self::type_name(),
576 message: Some("expected string or number".to_string()),
577 })?
578 .to_str()?
579 .to_owned()
580 .into_boxed_str())
581 }
582}
583
584impl IntoLua for CString {
585 #[inline]
586 fn into_lua(self, lua: &Lua) -> Result<Value> {
587 Ok(Value::String(lua.create_string(self.as_bytes())?))
588 }
589}
590
591impl FromLua for CString {
592 #[inline]
593 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
594 let ty = value.type_name();
595 let string = lua
596 .coerce_string(value)?
597 .ok_or_else(|| Error::FromLuaConversionError {
598 from: ty,
599 to: Self::type_name(),
600 message: Some("expected string or number".to_string()),
601 })?;
602
603 match CStr::from_bytes_with_nul(&string.as_bytes_with_nul()) {
604 Ok(s) => Ok(s.into()),
605 Err(_) => Err(Error::FromLuaConversionError {
606 from: ty,
607 to: Self::type_name(),
608 message: Some("invalid C-style string".to_string()),
609 }),
610 }
611 }
612}
613
614impl IntoLua for &CStr {
615 #[inline]
616 fn into_lua(self, lua: &Lua) -> Result<Value> {
617 Ok(Value::String(lua.create_string(self.to_bytes())?))
618 }
619}
620
621impl IntoLua for Cow<'_, CStr> {
622 #[inline]
623 fn into_lua(self, lua: &Lua) -> Result<Value> {
624 Ok(Value::String(lua.create_string(self.to_bytes())?))
625 }
626}
627
628impl IntoLua for BString {
629 #[inline]
630 fn into_lua(self, lua: &Lua) -> Result<Value> {
631 Ok(Value::String(lua.create_string(self)?))
632 }
633}
634
635impl FromLua for BString {
636 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
637 let ty = value.type_name();
638 match value {
639 Value::String(s) => Ok((*s.as_bytes()).into()),
640 Value::Buffer(buf) => Ok(buf.to_vec().into()),
641 _ => Ok((*lua
642 .coerce_string(value)?
643 .ok_or_else(|| Error::FromLuaConversionError {
644 from: ty,
645 to: Self::type_name(),
646 message: Some("expected string or number".to_string()),
647 })?
648 .as_bytes())
649 .into()),
650 }
651 }
652
653 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
654 match ffi::lua_type(state, idx) {
655 ffi::LUA_TSTRING => {
656 let mut size = 0;
657 let data = ffi::lua_tolstring(state, idx, &mut size);
658 Ok(slice::from_raw_parts(data as *const u8, size).into())
659 }
660 ffi::LUA_TBUFFER => {
661 let mut size = 0;
662 let buf = ffi::lua_tobuffer(state, idx, &mut size);
663 ulua_assert!(!buf.is_null(), "invalid Luau buffer");
664 Ok(slice::from_raw_parts(buf as *const u8, size).into())
665 }
666 type_id => {
667 Self::from_lua(lua.stack_value(idx, Some(type_id), state), lua.lua())
669 }
670 }
671 }
672}
673
674impl IntoLua for &BStr {
675 #[inline]
676 fn into_lua(self, lua: &Lua) -> Result<Value> {
677 Ok(Value::String(lua.create_string(self)?))
678 }
679}
680
681impl IntoLua for OsString {
682 #[inline]
683 fn into_lua(self, lua: &Lua) -> Result<Value> {
684 self.as_os_str().into_lua(lua)
685 }
686}
687
688impl FromLua for OsString {
689 #[inline]
690 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
691 let ty = value.type_name();
692 let bs = BString::from_lua(value, lua)?;
693 Vec::from(bs)
694 .into_os_string()
695 .map_err(|err| Error::FromLuaConversionError {
696 from: ty,
697 to: "OsString".into(),
698 message: Some(err.to_string()),
699 })
700 }
701}
702
703impl IntoLua for &OsStr {
704 #[inline]
705 fn into_lua(self, lua: &Lua) -> Result<Value> {
706 let s = <[u8]>::from_os_str(self).ok_or_else(|| Error::ToLuaConversionError {
707 from: "OsStr".into(),
708 to: "string",
709 message: Some("invalid utf-8 encoding".into()),
710 })?;
711 Ok(Value::String(lua.create_string(s)?))
712 }
713}
714
715impl IntoLua for PathBuf {
716 #[inline]
717 fn into_lua(self, lua: &Lua) -> Result<Value> {
718 self.as_os_str().into_lua(lua)
719 }
720}
721
722impl FromLua for PathBuf {
723 #[inline]
724 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
725 OsString::from_lua(value, lua).map(PathBuf::from)
726 }
727}
728
729impl IntoLua for &Path {
730 #[inline]
731 fn into_lua(self, lua: &Lua) -> Result<Value> {
732 self.as_os_str().into_lua(lua)
733 }
734}
735
736impl IntoLua for char {
737 #[inline]
738 fn into_lua(self, lua: &Lua) -> Result<Value> {
739 let mut char_bytes = [0; 4];
740 self.encode_utf8(&mut char_bytes);
741 Ok(Value::String(lua.create_string(&char_bytes[..self.len_utf8()])?))
742 }
743}
744
745impl FromLua for char {
746 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
747 let ty = value.type_name();
748 match value {
749 Value::Integer(i) => {
750 cast(i)
751 .and_then(char::from_u32)
752 .ok_or_else(|| Error::FromLuaConversionError {
753 from: ty,
754 to: "char".to_string(),
755 message: Some("integer out of range when converting to char".to_string()),
756 })
757 }
758 Value::String(s) => {
759 let str = s.to_str()?;
760 let mut str_iter = str.chars();
761 match (str_iter.next(), str_iter.next()) {
762 (Some(char), None) => Ok(char),
763 _ => Err(Error::FromLuaConversionError {
764 from: ty,
765 to: "char".to_string(),
766 message: Some(
767 "expected string to have exactly one char when converting to char".to_string(),
768 ),
769 }),
770 }
771 }
772 _ => Err(Error::FromLuaConversionError {
773 from: ty,
774 to: Self::type_name(),
775 message: Some("expected string or integer".to_string()),
776 }),
777 }
778 }
779}
780
781#[inline]
782unsafe fn push_bytes_into_stack<T>(this: T, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()>
783where
784 T: IntoLua + AsRef<[u8]>,
785{
786 let bytes = this.as_ref();
787 if lua.unlikely_memory_error() && bytes.len() < (1 << 30) {
788 ffi::lua_pushlstring(state, bytes.as_ptr() as *const _, bytes.len());
790 return Ok(());
791 }
792 lua.push_value(&T::into_lua(this, lua.lua())?, state)
794}
795
796macro_rules! lua_convert_int {
797 ($x:ty) => {
798 impl IntoLua for $x {
799 #[inline]
800 fn into_lua(self, _: &Lua) -> Result<Value> {
801 Ok(cast(self)
802 .map(Value::Integer)
803 .unwrap_or_else(|| Value::Number(self as ffi::lua_Number)))
804 }
805
806 #[inline]
807 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
808 match cast(self) {
809 Some(i) => ffi::lua_pushinteger(state, i),
810 None => ffi::lua_pushnumber(state, self as ffi::lua_Number),
811 }
812 Ok(())
813 }
814 }
815
816 impl FromLua for $x {
817 #[inline]
818 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
819 let ty = value.type_name();
820 (match value {
821 Value::Integer(i) => cast(i),
822 Value::Number(n) => cast(n),
823 _ => {
824 if let Some(i) = lua.coerce_integer(value.clone())? {
825 cast(i)
826 } else {
827 cast(
828 lua.coerce_number(value)?
829 .ok_or_else(|| Error::FromLuaConversionError {
830 from: ty,
831 to: stringify!($x).to_string(),
832 message: Some(
833 "expected number or string coercible to number".to_string(),
834 ),
835 })?,
836 )
837 }
838 }
839 })
840 .ok_or_else(|| Error::FromLuaConversionError {
841 from: ty,
842 to: stringify!($x).to_string(),
843 message: Some("out of range".to_owned()),
844 })
845 }
846
847 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
848 let type_id = ffi::lua_type(state, idx);
849 if type_id == ffi::LUA_TNUMBER {
850 let mut ok = 0;
851 let i = ffi::lua_tointegerx(state, idx, &mut ok);
852 if ok != 0 {
853 return cast(i).ok_or_else(|| Error::FromLuaConversionError {
854 from: "integer",
855 to: stringify!($x).to_string(),
856 message: Some("out of range".to_owned()),
857 });
858 }
859 }
860 Self::from_lua(lua.stack_value(idx, Some(type_id), state), lua.lua())
862 }
863 }
864 };
865}
866
867lua_convert_int!(i8);
868lua_convert_int!(u8);
869lua_convert_int!(i16);
870lua_convert_int!(u16);
871lua_convert_int!(i32);
872lua_convert_int!(u32);
873lua_convert_int!(i64);
874lua_convert_int!(u64);
875lua_convert_int!(i128);
876lua_convert_int!(u128);
877lua_convert_int!(isize);
878lua_convert_int!(usize);
879
880macro_rules! lua_convert_float {
881 ($x:ty) => {
882 impl IntoLua for $x {
883 #[inline]
884 fn into_lua(self, _: &Lua) -> Result<Value> {
885 Ok(Value::Number(self as _))
886 }
887 }
888
889 impl FromLua for $x {
890 #[inline]
891 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
892 let ty = value.type_name();
893 lua.coerce_number(value)?
894 .map(|n| n as $x)
895 .ok_or_else(|| Error::FromLuaConversionError {
896 from: ty,
897 to: stringify!($x).to_string(),
898 message: Some("expected number or string coercible to number".to_string()),
899 })
900 }
901
902 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
903 let type_id = ffi::lua_type(state, idx);
904 if type_id == ffi::LUA_TNUMBER {
905 return Ok(ffi::lua_tonumber(state, idx) as _);
906 }
907 Self::from_lua(lua.stack_value(idx, Some(type_id), state), lua.lua())
909 }
910 }
911 };
912}
913
914lua_convert_float!(f32);
915lua_convert_float!(f64);
916
917impl<T> IntoLua for &[T]
918where
919 T: IntoLua + Clone,
920{
921 #[inline]
922 fn into_lua(self, lua: &Lua) -> Result<Value> {
923 Ok(Value::Table(lua.create_sequence_from(self.iter().cloned())?))
924 }
925}
926
927impl<T, const N: usize> IntoLua for [T; N]
928where
929 T: IntoLua,
930{
931 #[inline]
932 fn into_lua(self, lua: &Lua) -> Result<Value> {
933 Ok(Value::Table(lua.create_sequence_from(self)?))
934 }
935}
936
937impl<T, const N: usize> FromLua for [T; N]
938where
939 T: FromLua,
940{
941 #[inline]
942 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
943 match value {
944 #[rustfmt::skip]
945 Value::Vector(v) if N == crate::Vector::SIZE => unsafe {
946 use std::{mem, ptr};
947 let mut arr: [mem::MaybeUninit<T>; N] = mem::MaybeUninit::uninit().assume_init();
948 ptr::write(arr[0].as_mut_ptr() , T::from_lua(Value::Number(v.x() as _), _lua)?);
949 ptr::write(arr[1].as_mut_ptr(), T::from_lua(Value::Number(v.y() as _), _lua)?);
950 ptr::write(arr[2].as_mut_ptr(), T::from_lua(Value::Number(v.z() as _), _lua)?);
951 #[cfg(feature = "vector4")]
952 ptr::write(arr[3].as_mut_ptr(), T::from_lua(Value::Number(v.w() as _), _lua)?);
953 Ok(mem::transmute_copy(&arr))
954 },
955 Value::Table(table) => {
956 let vec = table.sequence_values().collect::<Result<Vec<_>>>()?;
957 vec.try_into()
958 .map_err(|vec: Vec<T>| Error::FromLuaConversionError {
959 from: "table",
960 to: Self::type_name(),
961 message: Some(format!("expected table of length {N}, got {}", vec.len())),
962 })
963 }
964 _ => Err(Error::FromLuaConversionError {
965 from: value.type_name(),
966 to: Self::type_name(),
967 message: Some("expected table".to_string()),
968 }),
969 }
970 }
971}
972
973impl<T: IntoLua> IntoLua for Box<[T]> {
974 #[inline]
975 fn into_lua(self, lua: &Lua) -> Result<Value> {
976 Ok(Value::Table(lua.create_sequence_from(self.into_vec())?))
977 }
978}
979
980impl<T: FromLua> FromLua for Box<[T]> {
981 #[inline]
982 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
983 Ok(Vec::<T>::from_lua(value, lua)?.into_boxed_slice())
984 }
985}
986
987impl<T: IntoLua> IntoLua for Vec<T> {
988 #[inline]
989 fn into_lua(self, lua: &Lua) -> Result<Value> {
990 Ok(Value::Table(lua.create_sequence_from(self)?))
991 }
992}
993
994impl<T: FromLua> FromLua for Vec<T> {
995 #[inline]
996 fn from_lua(value: Value, _lua: &Lua) -> Result<Self> {
997 match value {
998 Value::Table(table) => table.sequence_values().collect(),
999 _ => Err(Error::FromLuaConversionError {
1000 from: value.type_name(),
1001 to: Self::type_name(),
1002 message: Some("expected table".to_string()),
1003 }),
1004 }
1005 }
1006}
1007
1008impl<K: Eq + Hash + IntoLua, V: IntoLua, S: BuildHasher> IntoLua for HashMap<K, V, S> {
1009 #[inline]
1010 fn into_lua(self, lua: &Lua) -> Result<Value> {
1011 Ok(Value::Table(lua.create_table_from(self)?))
1012 }
1013}
1014
1015impl<K: Eq + Hash + FromLua, V: FromLua, S: BuildHasher + Default> FromLua for HashMap<K, V, S> {
1016 #[inline]
1017 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
1018 if let Value::Table(table) = value {
1019 table.pairs().collect()
1020 } else {
1021 Err(Error::FromLuaConversionError {
1022 from: value.type_name(),
1023 to: Self::type_name(),
1024 message: Some("expected table".to_string()),
1025 })
1026 }
1027 }
1028}
1029
1030impl<K: Ord + IntoLua, V: IntoLua> IntoLua for BTreeMap<K, V> {
1031 #[inline]
1032 fn into_lua(self, lua: &Lua) -> Result<Value> {
1033 Ok(Value::Table(lua.create_table_from(self)?))
1034 }
1035}
1036
1037impl<K: Ord + FromLua, V: FromLua> FromLua for BTreeMap<K, V> {
1038 #[inline]
1039 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
1040 if let Value::Table(table) = value {
1041 table.pairs().collect()
1042 } else {
1043 Err(Error::FromLuaConversionError {
1044 from: value.type_name(),
1045 to: Self::type_name(),
1046 message: Some("expected table".to_string()),
1047 })
1048 }
1049 }
1050}
1051
1052impl<T: Eq + Hash + IntoLua, S: BuildHasher> IntoLua for HashSet<T, S> {
1053 #[inline]
1054 fn into_lua(self, lua: &Lua) -> Result<Value> {
1055 Ok(Value::Table(
1056 lua.create_table_from(self.into_iter().map(|val| (val, true)))?,
1057 ))
1058 }
1059}
1060
1061impl<T: Eq + Hash + FromLua, S: BuildHasher + Default> FromLua for HashSet<T, S> {
1062 #[inline]
1063 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
1064 match value {
1065 Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
1066 Value::Table(table) => table.pairs::<T, Value>().map(|res| res.map(|(k, _)| k)).collect(),
1067 _ => Err(Error::FromLuaConversionError {
1068 from: value.type_name(),
1069 to: Self::type_name(),
1070 message: Some("expected table".to_string()),
1071 }),
1072 }
1073 }
1074}
1075
1076impl<T: Ord + IntoLua> IntoLua for BTreeSet<T> {
1077 #[inline]
1078 fn into_lua(self, lua: &Lua) -> Result<Value> {
1079 Ok(Value::Table(
1080 lua.create_table_from(self.into_iter().map(|val| (val, true)))?,
1081 ))
1082 }
1083}
1084
1085impl<T: Ord + FromLua> FromLua for BTreeSet<T> {
1086 #[inline]
1087 fn from_lua(value: Value, _: &Lua) -> Result<Self> {
1088 match value {
1089 Value::Table(table) if table.raw_len() > 0 => table.sequence_values().collect(),
1090 Value::Table(table) => table.pairs::<T, Value>().map(|res| res.map(|(k, _)| k)).collect(),
1091 _ => Err(Error::FromLuaConversionError {
1092 from: value.type_name(),
1093 to: Self::type_name(),
1094 message: Some("expected table".to_string()),
1095 }),
1096 }
1097 }
1098}
1099
1100impl<T: IntoLua> IntoLua for Option<T> {
1101 #[inline]
1102 fn into_lua(self, lua: &Lua) -> Result<Value> {
1103 match self {
1104 Some(val) => val.into_lua(lua),
1105 None => Ok(Nil),
1106 }
1107 }
1108
1109 #[inline]
1110 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
1111 match self {
1112 Some(val) => val.push_into_stack(lua, state)?,
1113 None => ffi::lua_pushnil(state),
1114 }
1115 Ok(())
1116 }
1117}
1118
1119impl<T: FromLua> FromLua for Option<T> {
1120 #[inline]
1121 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
1122 match value {
1123 Nil => Ok(None),
1124 value => Ok(Some(T::from_lua(value, lua)?)),
1125 }
1126 }
1127
1128 #[inline]
1129 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
1130 match ffi::lua_type(state, idx) {
1131 ffi::LUA_TNIL => Ok(None),
1132 _ => Ok(Some(T::from_stack(idx, lua, state)?)),
1133 }
1134 }
1135}
1136
1137impl<L: IntoLua, R: IntoLua> IntoLua for Either<L, R> {
1138 #[inline]
1139 fn into_lua(self, lua: &Lua) -> Result<Value> {
1140 match self {
1141 Either::Left(l) => l.into_lua(lua),
1142 Either::Right(r) => r.into_lua(lua),
1143 }
1144 }
1145
1146 #[inline]
1147 unsafe fn push_into_stack(self, lua: &RawLua, state: *mut ffi::lua_State) -> Result<()> {
1148 match self {
1149 Either::Left(l) => l.push_into_stack(lua, state),
1150 Either::Right(r) => r.push_into_stack(lua, state),
1151 }
1152 }
1153}
1154
1155impl<L: FromLua, R: FromLua> FromLua for Either<L, R> {
1156 #[inline]
1157 fn from_lua(value: Value, lua: &Lua) -> Result<Self> {
1158 let value_type_name = value.type_name();
1159 match L::from_lua(value.clone(), lua) {
1161 Ok(l) => Ok(Either::Left(l)),
1162 Err(_) => match R::from_lua(value, lua).map(Either::Right) {
1164 Ok(r) => Ok(r),
1165 Err(_) => Err(Error::FromLuaConversionError {
1166 from: value_type_name,
1167 to: Self::type_name(),
1168 message: None,
1169 }),
1170 },
1171 }
1172 }
1173
1174 #[inline]
1175 unsafe fn from_stack(idx: c_int, lua: &RawLua, state: *mut ffi::lua_State) -> Result<Self> {
1176 match L::from_stack(idx, lua, state) {
1177 Ok(l) => Ok(Either::Left(l)),
1178 Err(_) => match R::from_stack(idx, lua, state).map(Either::Right) {
1179 Ok(r) => Ok(r),
1180 Err(_) => {
1181 let value_type_name = CStr::from_ptr(ffi::luaL_typename(state, idx));
1182 Err(Error::FromLuaConversionError {
1183 from: value_type_name.to_str().unwrap(),
1184 to: Self::type_name(),
1185 message: None,
1186 })
1187 }
1188 },
1189 }
1190 }
1191}