luajit_bindings/
pushable.rs1use std::ffi::{c_char, c_int};
2
3use crate::ffi::{self, lua_Integer, lua_Number, lua_State};
4use crate::macros::count;
5
6pub trait Pushable {
8 unsafe fn push(
11 self,
12 lstate: *mut lua_State,
13 ) -> Result<c_int, crate::Error>;
14}
15
16impl Pushable for () {
17 unsafe fn push(
18 self,
19 lstate: *mut lua_State,
20 ) -> Result<c_int, crate::Error> {
21 ffi::lua_pushnil(lstate);
22 Ok(1)
23 }
24}
25
26impl Pushable for bool {
27 unsafe fn push(
28 self,
29 lstate: *mut lua_State,
30 ) -> Result<c_int, crate::Error> {
31 ffi::lua_pushboolean(lstate, self as _);
32 Ok(1)
33 }
34}
35
36impl Pushable for lua_Integer {
37 unsafe fn push(
38 self,
39 lstate: *mut lua_State,
40 ) -> Result<c_int, crate::Error> {
41 ffi::lua_pushinteger(lstate, self);
42 Ok(1)
43 }
44}
45
46macro_rules! push_into_integer {
49 ($integer:ty) => {
50 impl Pushable for $integer {
51 unsafe fn push(
52 self,
53 lstate: *mut lua_State,
54 ) -> Result<c_int, crate::Error> {
55 let n: lua_Integer = self.into();
56 n.push(lstate)
57 }
58 }
59 };
60}
61
62macro_rules! push_try_into_integer {
65 ($integer:ty) => {
66 impl Pushable for $integer {
67 unsafe fn push(
68 self,
69 lstate: *mut lua_State,
70 ) -> Result<c_int, crate::Error> {
71 let n: lua_Integer = self.try_into().map_err(
72 |err: std::num::TryFromIntError| {
73 crate::Error::push_error(
74 std::any::type_name::<$integer>(),
75 err.to_string(),
76 )
77 },
78 )?;
79 n.push(lstate)
80 }
81 }
82 };
83}
84
85push_into_integer!(i8);
86push_into_integer!(u8);
87push_into_integer!(i16);
88push_try_into_integer!(u16);
89push_try_into_integer!(i32);
90push_try_into_integer!(u32);
91push_try_into_integer!(i64);
92push_try_into_integer!(u64);
93push_try_into_integer!(usize);
94
95impl Pushable for lua_Number {
96 unsafe fn push(
97 self,
98 lstate: *mut lua_State,
99 ) -> Result<c_int, crate::Error> {
100 ffi::lua_pushnumber(lstate, self);
101 Ok(1)
102 }
103}
104
105impl Pushable for f32 {
106 unsafe fn push(
107 self,
108 lstate: *mut lua_State,
109 ) -> Result<c_int, crate::Error> {
110 (self as lua_Number).push(lstate)
111 }
112}
113
114impl Pushable for String {
115 unsafe fn push(
116 self,
117 lstate: *mut lua_State,
118 ) -> Result<c_int, crate::Error> {
119 ffi::lua_pushlstring(
120 lstate,
121 self.as_ptr() as *const c_char,
122 self.len(),
123 );
124 Ok(1)
125 }
126}
127
128impl<T> Pushable for Option<T>
129where
130 T: Pushable,
131{
132 unsafe fn push(
133 self,
134 lstate: *mut lua_State,
135 ) -> Result<c_int, crate::Error> {
136 match self {
137 Some(t) => t.push(lstate),
138 None => ().push(lstate),
139 }
140 }
141}
142
143impl<T> Pushable for Vec<T>
144where
145 T: Pushable,
146{
147 unsafe fn push(
148 self,
149 lstate: *mut lua_State,
150 ) -> Result<c_int, crate::Error> {
151 ffi::lua_createtable(lstate, self.len() as _, 0);
152
153 for (i, obj) in self.into_iter().enumerate() {
154 obj.push(lstate)?;
155 ffi::lua_rawseti(lstate, -2, (i + 1) as _);
156 }
157
158 Ok(1)
159 }
160}
161
162macro_rules! push_tuple {
165 ($($name:ident)*) => {
166 impl<$($name,)*> Pushable for ($($name,)*)
167 where
168 $($name: Pushable,)*
169 {
170 #[allow(non_snake_case)]
171 unsafe fn push(
172 self,
173 lstate: *mut lua_State,
174 ) -> Result<c_int, crate::Error> {
175 let ($($name,)*) = self;
176 $($name.push(lstate)?;)*
177 Ok(count!($($name)*))
178 }
179 }
180 }
181}
182
183push_tuple!(A);
184push_tuple!(A B);
185push_tuple!(A B C);
186push_tuple!(A B C D);
187push_tuple!(A B C D E);
188push_tuple!(A B C D E F);
189push_tuple!(A B C D E F G);
190push_tuple!(A B C D E F G H);
191push_tuple!(A B C D E F G H I);
192push_tuple!(A B C D E F G H I J);
193push_tuple!(A B C D E F G H I J K);
194push_tuple!(A B C D E F G H I J K L);
195push_tuple!(A B C D E F G H I J K L M);
196push_tuple!(A B C D E F G H I J K L M N);
197push_tuple!(A B C D E F G H I J K L M N O);
198push_tuple!(A B C D E F G H I J K L M N O P);