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