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