1use crate::{
2 impl_object, AbsoluteIndex, AsLua, LuaError, LuaRead, LuaState, Push, PushGuard, PushInto,
3 PushOneInto, ReadResult, Void,
4};
5use std::{error::Error, fmt, num::NonZeroI32};
6
7#[derive(Debug)]
19pub struct Object<L> {
20 guard: L,
21 index: AbsoluteIndex,
22}
23
24impl<L: AsLua> Object<L> {
25 #[inline(always)]
26 pub(crate) fn new(guard: L, index: NonZeroI32) -> Self
27 where
28 L: AsLua,
29 {
30 Self {
31 index: AbsoluteIndex::new(index, guard.as_lua()),
32 guard,
33 }
34 }
35
36 #[inline(always)]
37 pub fn guard(&self) -> &L {
38 &self.guard
39 }
40
41 #[inline(always)]
42 pub fn into_guard(self) -> L {
43 self.guard
44 }
45
46 #[inline(always)]
47 pub fn index(&self) -> AbsoluteIndex {
48 self.index
49 }
50
51 #[inline(always)]
58 pub unsafe fn try_downcast<T>(self) -> Result<T, Self>
59 where
60 T: LuaRead<L>,
61 {
62 let Self { guard, index } = self;
63 T::lua_read_at_position(guard, index.0).map_err(|(guard, _)| Self { guard, index })
64 }
65}
66
67impl<L> AsLua for Object<L>
68where
69 L: AsLua,
70{
71 fn as_lua(&self) -> LuaState {
72 self.guard.as_lua()
73 }
74}
75
76impl<L> LuaRead<L> for Object<L>
77where
78 L: AsLua,
79{
80 fn lua_read_at_position(lua: L, index: NonZeroI32) -> ReadResult<Self, L> {
81 Ok(Self::new(lua, index))
82 }
83}
84
85impl<L, K> Push<L> for Object<K>
86where
87 L: AsLua,
88 K: AsLua,
89{
90 type Err = Void;
91 fn push_to_lua(&self, lua: L) -> crate::PushResult<L, Self> {
92 unsafe {
93 crate::ffi::lua_pushvalue(lua.as_lua(), self.index.into());
94 Ok(PushGuard::new(lua, 1))
95 }
96 }
97}
98impl<L> crate::PushOne<L> for Object<L> where L: AsLua {}
99
100impl<L, K> PushInto<L> for Object<K>
101where
102 L: AsLua,
103 K: AsLua,
104{
105 type Err = Void;
106 fn push_into_lua(self, lua: L) -> crate::PushIntoResult<L, Self> {
107 unsafe {
108 crate::ffi::lua_pushvalue(lua.as_lua(), self.index.into());
109 Ok(PushGuard::new(lua, 1))
110 }
111 }
112}
113impl<L> crate::PushOneInto<L> for Object<L> where L: AsLua {}
114
115pub trait FromObject<L: AsLua> {
119 unsafe fn check(lua: impl AsLua, index: NonZeroI32) -> bool;
121
122 unsafe fn from_obj(inner: Object<L>) -> Self;
124
125 fn try_from_obj(inner: Object<L>) -> Result<Self, Object<L>>
126 where
127 Self: Sized,
128 L: AsLua,
129 {
130 if unsafe { Self::check(inner.guard(), inner.index().0) } {
131 Ok(unsafe { Self::from_obj(inner) })
132 } else {
133 Err(inner)
134 }
135 }
136}
137
138pub trait Index<L>: AsRef<Object<L>>
146where
147 L: AsLua,
148{
149 #[track_caller]
156 #[inline(always)]
157 fn get<'lua, K, R>(&'lua self, key: K) -> Option<R>
158 where
159 L: 'lua,
160 K: PushOneInto<LuaState>,
161 K::Err: Into<Void>,
162 R: LuaRead<PushGuard<&'lua L>>,
163 {
164 self.try_get(key).ok()
165 }
166
167 #[track_caller]
180 #[inline]
181 fn try_get<'lua, K, R>(&'lua self, key: K) -> Result<R, LuaError>
182 where
183 L: 'lua,
184 K: PushOneInto<LuaState>,
185 K::Err: Into<Void>,
186 R: LuaRead<PushGuard<&'lua L>>,
187 {
188 let Object { guard, index } = self.as_ref();
189 unsafe { imp::try_get(guard, *index, key).map_err(|(_, e)| e) }
190 }
191
192 #[track_caller]
198 #[inline(always)]
199 fn into_get<K, R>(self, key: K) -> Result<R, Self>
200 where
201 Self: AsLua + Sized,
202 K: PushOneInto<LuaState>,
203 K::Err: Into<Void>,
204 R: LuaRead<PushGuard<Self>>,
205 {
206 self.try_into_get(key).map_err(|(this, _)| this)
207 }
208
209 #[track_caller]
221 #[inline]
222 fn try_into_get<K, R>(self, key: K) -> Result<R, (Self, LuaError)>
223 where
224 Self: AsLua + Sized,
225 K: PushOneInto<LuaState>,
226 K::Err: Into<Void>,
227 R: LuaRead<PushGuard<Self>>,
228 {
229 let this_index = self.as_ref().index;
230 unsafe { imp::try_get(self, this_index, key) }
231 }
232
233 #[track_caller]
241 #[inline]
242 fn call_method<'lua, A, R>(
243 &'lua self,
244 name: &str,
245 args: A,
246 ) -> Result<R, MethodCallError<A::Err>>
247 where
248 L: 'lua,
249 Self: Push<LuaState>,
250 Self::Err: Into<Void>,
251 A: PushInto<LuaState>,
252 R: LuaRead<PushGuard<Callable<PushGuard<&'lua L>>>>,
253 {
254 use MethodCallError::{LuaError, NoSuchMethod, PushError};
255
256 self.get::<_, Callable<_>>(name)
257 .ok_or(NoSuchMethod)?
258 .into_call_with((self, args))
259 .map_err(|e| match e {
260 CallError::LuaError(e) => LuaError(e),
261 CallError::PushError(e) => PushError(e.other().first()),
262 })
263 }
264}
265
266#[derive(Debug)]
267pub enum MethodCallError<E> {
268 NoSuchMethod,
270 LuaError(LuaError),
272 PushError(E),
274}
275
276impl<E> From<CallError<E>> for MethodCallError<E> {
277 fn from(e: CallError<E>) -> Self {
278 match e {
279 CallError::PushError(e) => Self::PushError(e),
280 CallError::LuaError(e) => Self::LuaError(e),
281 }
282 }
283}
284
285impl<E> fmt::Display for MethodCallError<E>
286where
287 E: fmt::Display,
288{
289 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
290 match self {
291 Self::NoSuchMethod => f.write_str("Method not found"),
292 Self::LuaError(lua_error) => write!(f, "Lua error: {}", lua_error),
293 Self::PushError(err) => {
294 write!(f, "Error while pushing arguments: {}", err)
295 }
296 }
297 }
298}
299
300impl<E> Error for MethodCallError<E>
301where
302 E: Error,
303{
304 fn description(&self) -> &str {
305 match self {
306 Self::NoSuchMethod => "Method not found",
307 Self::LuaError(_) => "Lua error",
308 Self::PushError(_) => "Error while pushing arguments",
309 }
310 }
311
312 fn cause(&self) -> Option<&dyn Error> {
313 match self {
314 Self::NoSuchMethod => None,
315 Self::LuaError(lua_error) => Some(lua_error),
316 Self::PushError(err) => Some(err),
317 }
318 }
319}
320
321#[derive(Debug)]
332pub struct Indexable<L> {
333 inner: Object<L>,
334}
335
336impl_object! { Indexable,
337 check(lua, index) {
338 imp::is_indexable(&lua, index)
339 }
340 impl Index,
341}
342
343pub trait NewIndex<L>: AsRef<Object<L>>
351where
352 L: AsLua,
353{
354 #[track_caller]
370 #[inline(always)]
371 fn set<K, V>(&self, key: K, value: V)
372 where
373 K: PushOneInto<LuaState>,
374 K::Err: Into<Void>,
375 V: PushOneInto<LuaState>,
376 V::Err: Into<Void>,
377 {
378 if let Err(e) = self.try_set(key, value) {
379 panic!("Setting value failed: {}", e)
380 }
381 }
382
383 #[track_caller]
397 #[inline]
398 fn try_set<K, V>(&self, key: K, value: V) -> Result<(), LuaError>
399 where
400 K: PushOneInto<LuaState>,
401 K::Err: Into<Void>,
402 V: PushOneInto<LuaState>,
403 V::Err: Into<Void>,
404 {
405 let Object { guard, index } = self.as_ref();
406 unsafe { imp::try_checked_set(guard, *index, key, value) }.map_err(|e| match e {
407 Ok(_) => unreachable!("Void is uninstantiatable"),
408 Err(e) => e,
409 })
410 }
411
412 #[track_caller]
426 #[inline(always)]
427 fn checked_set<K, V>(&self, key: K, value: V) -> Result<(), CheckedSetError<K::Err, V::Err>>
428 where
429 K: PushOneInto<LuaState>,
430 V: PushOneInto<LuaState>,
431 {
432 self.try_checked_set(key, value)
433 .map_err(|e| e.unwrap_or_else(|e| panic!("Setting value failed: {}", e)))
434 }
435
436 #[track_caller]
446 #[inline(always)]
447 fn try_checked_set<K, V>(
448 &self,
449 key: K,
450 value: V,
451 ) -> Result<(), TryCheckedSetError<K::Err, V::Err>>
452 where
453 K: PushOneInto<LuaState>,
454 V: PushOneInto<LuaState>,
455 {
456 let Object { guard, index } = self.as_ref();
457 unsafe { imp::try_checked_set(guard, *index, key, value) }
458 }
459}
460
461pub type TryCheckedSetError<K, V> = Result<CheckedSetError<K, V>, LuaError>;
462
463#[derive(Debug, Copy, Clone)]
465pub enum CheckedSetError<K, V> {
466 KeyPushError(K),
468 ValuePushError(V),
470}
471
472#[derive(Debug)]
483pub struct IndexableRW<L> {
484 inner: Object<L>,
485}
486
487impl_object! { IndexableRW,
488 check(lua, index) {
489 imp::is_rw_indexable(&lua, index)
490 }
491 impl Index,
492 impl NewIndex,
493}
494
495pub trait Call<L>: AsRef<Object<L>>
500where
501 L: AsLua,
502{
503 #[track_caller]
504 #[inline]
505 fn call<'lua, R>(&'lua self) -> Result<R, LuaError>
506 where
507 L: 'lua,
508 R: LuaRead<PushGuard<&'lua L>>,
509 {
510 Ok(self.call_with(())?)
511 }
512
513 #[track_caller]
514 #[inline]
515 fn call_with<'lua, A, R>(&'lua self, args: A) -> Result<R, CallError<A::Err>>
516 where
517 L: 'lua,
518 A: PushInto<LuaState>,
519 R: LuaRead<PushGuard<&'lua L>>,
520 {
521 let Object { guard, index } = self.as_ref();
522 imp::call(guard, *index, args)
523 }
524
525 #[track_caller]
526 #[inline]
527 fn into_call<R>(self) -> Result<R, LuaError>
528 where
529 Self: AsLua + Sized,
530 R: LuaRead<PushGuard<Self>>,
531 {
532 Ok(self.into_call_with(())?)
533 }
534
535 #[track_caller]
536 #[inline]
537 fn into_call_with<A, R>(self, args: A) -> Result<R, CallError<A::Err>>
538 where
539 Self: AsLua + Sized,
540 A: PushInto<LuaState>,
541 R: LuaRead<PushGuard<Self>>,
542 {
543 let index = self.as_ref().index;
544 imp::call(self, index, args)
545 }
546}
547
548#[derive(Debug)]
550pub enum CallError<E> {
551 LuaError(LuaError),
553 PushError(E),
555}
556
557impl<E> CallError<E> {
558 pub fn map<F, R>(self, f: F) -> CallError<R>
559 where
560 F: FnOnce(E) -> R,
561 {
562 match self {
563 CallError::LuaError(e) => CallError::LuaError(e),
564 CallError::PushError(e) => CallError::PushError(f(e)),
565 }
566 }
567}
568
569impl<E> From<LuaError> for CallError<E> {
570 fn from(e: LuaError) -> Self {
571 Self::LuaError(e)
572 }
573}
574
575impl<E> From<CallError<E>> for LuaError
576where
577 E: Into<Void>,
578{
579 fn from(e: CallError<E>) -> Self {
580 match e {
581 CallError::LuaError(le) => le,
582 CallError::PushError(_) => {
583 unreachable!("no way to create instance of Void")
584 }
585 }
586 }
587}
588
589impl<E> fmt::Display for CallError<E>
590where
591 E: fmt::Display,
592{
593 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594 match self {
595 Self::LuaError(lua_error) => write!(f, "Lua error: {}", lua_error),
596 Self::PushError(err) => {
597 write!(f, "Error while pushing arguments: {}", err)
598 }
599 }
600 }
601}
602
603impl<E> Error for CallError<E>
604where
605 E: Error,
606{
607 fn description(&self) -> &str {
608 match self {
609 Self::LuaError(_) => "Lua error",
610 Self::PushError(_) => "error while pushing arguments",
611 }
612 }
613
614 fn cause(&self) -> Option<&dyn Error> {
615 match self {
616 Self::LuaError(lua_error) => Some(lua_error),
617 Self::PushError(err) => Some(err),
618 }
619 }
620}
621
622#[derive(Debug)]
633pub struct Callable<L> {
634 inner: Object<L>,
635}
636
637impl_object! { Callable,
638 check(lua, index) {
639 imp::is_callable(&lua, index)
640 }
641 impl Call,
642}
643
644mod imp {
649 use super::{CallError, CheckedSetError, TryCheckedSetError};
650 use crate::{
651 c_ptr, ffi, nzi32, AbsoluteIndex, AsLua, LuaError, LuaRead, LuaState, PushGuard, PushInto,
652 PushOneInto, ToString, Void, WrongType,
653 };
654 use std::num::NonZeroI32;
655
656 #[track_caller]
661 pub(super) unsafe fn try_get<T, K, R>(
662 this: T,
663 this_index: AbsoluteIndex,
664 key: K,
665 ) -> Result<R, (T, LuaError)>
666 where
667 T: AsLua,
668 K: PushOneInto<LuaState>,
669 K::Err: Into<Void>,
670 R: LuaRead<PushGuard<T>>,
671 {
672 let raw_lua = this.as_lua();
673 let this_index = this_index.into();
674
675 if ffi::lua_istable(raw_lua, this_index)
676 && !ffi::luaL_hasmetafield(raw_lua, this_index, c_ptr!("__index"))
677 {
678 raw_lua.push_one(key).assert_one_and_forget();
680 ffi::lua_rawget(raw_lua, this_index);
682 } else {
683 raw_lua.push_one(key).assert_one_and_forget();
685 let index_ref = ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX);
687 ffi::lua_pushvalue(raw_lua, this_index);
689 let table_ref = ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX);
691
692 let res = raw_lua.pcall(|l| {
693 let raw_lua = l.as_lua();
694 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, table_ref);
696 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, index_ref);
698 ffi::lua_gettable(raw_lua, -2);
700 ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX)
702 });
704 let value_ref = match res {
705 Ok(value_ref) => value_ref,
706 Err(e) => return Err((this, e)),
707 };
708
709 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, value_ref);
711
712 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, value_ref);
714 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, index_ref);
715 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, table_ref);
716 }
717
718 R::lua_read_at_position(PushGuard::new(this, 1), nzi32!(-1)).map_err(|(g, e)| {
719 let e = WrongType::info("reading value from Lua table")
720 .expected_type::<R>()
721 .actual_single_lua(raw_lua, nzi32!(-1))
722 .subtype(e);
723 (g.into_inner(), e.into())
724 })
725 }
726
727 #[track_caller]
732 pub(super) unsafe fn try_checked_set<T, K, V>(
733 this: T,
734 this_index: AbsoluteIndex,
735 key: K,
736 value: V,
737 ) -> Result<(), TryCheckedSetError<K::Err, V::Err>>
738 where
739 T: AsLua,
740 K: PushOneInto<LuaState>,
741 V: PushOneInto<LuaState>,
742 {
743 let raw_lua = this.as_lua();
744 let this_index = this_index.into();
745 if ffi::lua_istable(raw_lua, this_index)
746 && !ffi::luaL_hasmetafield(raw_lua, this_index, c_ptr!("__index"))
747 && !ffi::luaL_hasmetafield(raw_lua, this_index, c_ptr!("__newindex"))
748 {
749 raw_lua
751 .try_push_one(key)
752 .map_err(|(e, _)| Ok(CheckedSetError::KeyPushError(e)))?
753 .assert_one_and_forget();
754 raw_lua
756 .try_push_one(value)
757 .map_err(|(e, _)| Ok(CheckedSetError::ValuePushError(e)))?
758 .assert_one_and_forget();
759 ffi::lua_rawset(raw_lua, this_index);
761 } else {
762 raw_lua
764 .try_push_one(value)
765 .map_err(|(e, _)| Ok(CheckedSetError::ValuePushError(e)))?
766 .assert_one_and_forget();
767 let value_ref = ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX);
769
770 raw_lua
772 .try_push_one(key)
773 .map_err(|(e, _)| Ok(CheckedSetError::KeyPushError(e)))?
774 .assert_one_and_forget();
775 let index_ref = ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX);
777
778 ffi::lua_pushvalue(raw_lua, this_index);
780 let table_ref = ffi::luaL_ref(raw_lua, ffi::LUA_REGISTRYINDEX);
782
783 raw_lua
784 .pcall(|l| {
785 let raw_lua = l.as_lua();
786 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, table_ref);
788 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, index_ref);
790 ffi::lua_rawgeti(raw_lua, ffi::LUA_REGISTRYINDEX, value_ref);
792 ffi::lua_settable(raw_lua, -3);
794 })
796 .map_err(Err)?;
797
798 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, value_ref);
800 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, index_ref);
801 ffi::luaL_unref(raw_lua, ffi::LUA_REGISTRYINDEX, table_ref);
802 }
803 Ok(())
804 }
805
806 #[track_caller]
811 #[inline]
812 pub(super) fn call<T, A, R>(
813 this: T,
814 index: AbsoluteIndex,
815 args: A,
816 ) -> Result<R, CallError<A::Err>>
817 where
818 T: AsLua,
819 A: PushInto<LuaState>,
820 R: LuaRead<PushGuard<T>>,
821 {
822 let raw_lua = this.as_lua();
823 let (pcall_return_value, pushed_value) = unsafe {
825 let old_top = ffi::lua_gettop(raw_lua);
826 ffi::lua_pushvalue(raw_lua, index.into());
828 let num_pushed = match this.as_lua().try_push(args) {
829 Ok(g) => g.forget_internal(),
830 Err((err, _)) => return Err(CallError::PushError(err)),
831 };
832 let pcall_return_value = ffi::lua_pcall(raw_lua, num_pushed, ffi::LUA_MULTRET, 0);
833 let n_results = ffi::lua_gettop(raw_lua) - old_top;
834 (pcall_return_value, PushGuard::new(this, n_results))
835 };
836
837 match pcall_return_value {
838 ffi::LUA_ERRMEM => panic!("lua_pcall returned LUA_ERRMEM"),
839 ffi::LUA_ERRRUN => {
840 let error_msg = ToString::lua_read(pushed_value)
841 .ok()
842 .expect("can't find error message at the top of the Lua stack");
843 return Err(LuaError::ExecutionError(error_msg.into()).into());
844 }
845 0 => {}
846 _ => panic!(
847 "Unknown error code returned by lua_pcall: {}",
848 pcall_return_value
849 ),
850 }
851
852 let n_results = pushed_value.size;
853 LuaRead::lua_read_at_maybe_zero_position(pushed_value, -n_results).map_err(|(lua, e)| {
854 WrongType::info("reading value(s) returned by Lua")
855 .expected_type::<R>()
856 .actual_multiple_lua(lua, n_results)
857 .subtype(e)
858 .into()
859 })
860 }
861
862 #[inline(always)]
867 pub(super) fn is_callable(lua: impl AsLua, index: NonZeroI32) -> bool {
868 let raw_lua = lua.as_lua();
869 let i = index.into();
870 unsafe {
871 ffi::lua_isfunction(raw_lua, i) || ffi::luaL_hasmetafield(raw_lua, i, c_ptr!("__call"))
873 }
874 }
875
876 #[inline(always)]
877 pub(super) fn is_indexable(lua: impl AsLua, index: NonZeroI32) -> bool {
878 let raw_lua = lua.as_lua();
879 let i = index.into();
880 unsafe {
881 ffi::lua_istable(raw_lua, i) || ffi::luaL_hasmetafield(raw_lua, i, c_ptr!("__index"))
882 }
883 }
884
885 #[inline(always)]
886 pub(super) fn is_rw_indexable(lua: impl AsLua, index: NonZeroI32) -> bool {
887 let raw_lua = lua.as_lua();
888 let i = index.into();
889 unsafe {
890 ffi::lua_istable(raw_lua, i)
891 || ffi::luaL_hasmetafield(raw_lua, i, c_ptr!("__index"))
892 && ffi::luaL_hasmetafield(raw_lua, i, c_ptr!("__newindex"))
893 }
894 }
895}
896
897#[macro_export]
902macro_rules! impl_object {
903 (
904 $this:ident,
905 check($lua:ident, $index:ident) { $($check:tt)* }
906 $( impl $trait:ident, )*
907 ) => {
908 impl<L> $crate::object::FromObject<L> for $this<L>
909 where
910 L: $crate::AsLua,
911 {
912 #[inline(always)]
915 unsafe fn check($lua: impl $crate::AsLua, $index: ::std::num::NonZeroI32) -> bool {
916 $($check)*
917 }
918
919 #[inline(always)]
923 unsafe fn from_obj(inner: $crate::object::Object<L>) -> Self {
924 Self { inner }
925 }
926 }
927
928 impl<L> $crate::AsLua for $this<L>
929 where
930 L: $crate::AsLua,
931 {
932 #[inline(always)]
933 fn as_lua(&self) -> $crate::LuaState {
934 self.inner.as_lua()
935 }
936 }
937
938 impl<L> ::std::convert::AsRef<$crate::object::Object<L>> for $this<L>
939 where
940 L: $crate::AsLua,
941 {
942 #[inline(always)]
943 fn as_ref(&self) -> &$crate::object::Object<L> {
944 &self.inner
945 }
946 }
947
948 impl<L> ::std::convert::From<$this<L>> for $crate::object::Object<L>
949 where
950 L: $crate::AsLua,
951 {
952 #[inline(always)]
953 fn from(o: $this<L>) -> Self {
954 o.inner
955 }
956 }
957
958 impl<L> ::std::convert::TryFrom<$crate::object::Object<L>> for $this<L>
959 where
960 L: $crate::AsLua,
961 {
962 type Error = $crate::object::Object<L>;
963
964 #[inline(always)]
965 fn try_from(o: $crate::object::Object<L>) -> ::std::result::Result<Self, Self::Error> {
966 Self::try_from_obj(o)
967 }
968 }
969
970 $(
971 impl<L> $trait<L> for $this<L>
972 where
973 L: $crate::AsLua,
974 {}
975 )*
976
977 impl<L> $crate::LuaRead<L> for $this<L>
978 where
979 L: $crate::AsLua,
980 {
981 #[inline(always)]
982 fn lua_read_at_position(
983 lua: L,
984 index: ::std::num::NonZeroI32,
985 ) -> $crate::ReadResult<Self, L> {
986 ::std::convert::TryFrom::try_from($crate::object::Object::new(lua, index))
987 .map_err(|l| {
988 let g = $crate::object::Object::into_guard(l);
989 let e = $crate::WrongType::info("reading lua value from stack")
990 .expected_type::<Self>()
991 .actual_single_lua(&g, index);
992 (g, e)
993 })
994 }
995 }
996
997 impl<L, T> $crate::Push<L> for $this<T>
998 where
999 L: $crate::AsLua,
1000 T: $crate::AsLua,
1001 {
1002 type Err = $crate::Void;
1003
1004 #[inline(always)]
1005 fn push_to_lua(&self, lua: L) -> $crate::PushResult<L, Self> {
1006 unsafe {
1007 $crate::ffi::lua_pushvalue(lua.as_lua(), self.as_ref().index().into());
1008 Ok(PushGuard::new(lua, 1))
1009 }
1010 }
1011 }
1012
1013 impl<L, T> $crate::PushOne<L> for $this<T>
1014 where
1015 L: $crate::AsLua,
1016 T: $crate::AsLua,
1017 {}
1018 }
1019}