1use std::path::Path;
2
3use mlua::{AnyUserData, FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Lua, Table, UserDataFields};
4
5mod module;
6
7pub use module::{LuaModule, Module, ModuleBuilder, ModuleFields, ModuleMethods, ExtendModule};
8
9use crate::MaybeSend;
10
11pub trait LuaExtras {
18 fn path(&self) -> mlua::Result<String>;
25
26 fn cpath(&self) -> mlua::Result<String>;
33
34 fn prepend_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
41
42 fn prepend_paths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>)
49 -> mlua::Result<()>;
50
51 fn append_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
58
59 fn append_paths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()>;
66
67 fn set_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
74
75 fn set_paths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()>;
82
83 fn prepend_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
90
91 fn prepend_cpaths<S: AsRef<Path>>(
98 &self,
99 paths: impl IntoIterator<Item = S>,
100 ) -> mlua::Result<()>;
101
102 fn append_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
109
110 fn append_cpaths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>)
117 -> mlua::Result<()>;
118
119 fn set_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()>;
126
127 fn set_cpaths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()>;
134
135 fn set_global<K, V>(&self, key: K, value: V) -> mlua::Result<()>
137 where
138 K: IntoLua,
139 V: IntoLua;
140
141 fn set_global_function<K, A, R, F>(&self, key: K, value: F) -> mlua::Result<()>
142 where
143 K: IntoLua,
144 A: FromLuaMulti,
145 R: IntoLuaMulti,
146 F: Fn(&Lua, A) -> mlua::Result<R> + Send + 'static;
147}
148
149impl LuaExtras for Lua {
150 fn set_global<K, V>(&self, key: K, value: V) -> mlua::Result<()>
151 where
152 K: IntoLua,
153 V: IntoLua,
154 {
155 self.globals().set(key, value)
156 }
157
158 fn set_global_function<K, A, R, F>(&self, key: K, value: F) -> mlua::Result<()>
159 where
160 K: IntoLua,
161 A: FromLuaMulti,
162 R: IntoLuaMulti,
163 F: Fn(&Lua, A) -> mlua::Result<R> + Send + 'static,
164 {
165 self.globals().set(key, self.create_function(value)?)
166 }
167
168 fn path(&self) -> mlua::Result<String> {
169 self.globals()
170 .get::<Table>("package")?
171 .get::<String>("path")
172 }
173
174 fn cpath(&self) -> mlua::Result<String> {
175 self.globals()
176 .get::<Table>("package")?
177 .get::<String>("cpath")
178 }
179
180 fn set_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
181 self.globals()
182 .get::<Table>("package")
183 .unwrap()
184 .set("path", path.as_ref().display().to_string())
185 }
186
187 fn set_paths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()> {
188 self.globals().get::<Table>("package").unwrap().set(
189 "path",
190 paths
191 .into_iter()
192 .map(|s| s.as_ref().display().to_string())
193 .collect::<Vec<_>>()
194 .join(";"),
195 )
196 }
197
198 fn prepend_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
199 let lua_path = match self.path()?.trim() {
200 "" => path.as_ref().display().to_string(),
201 other => format!("{};{other}", path.as_ref().display()),
202 };
203 self.globals()
204 .get::<Table>("package")?
205 .set("path", lua_path)
206 }
207
208 fn prepend_paths<S: AsRef<Path>>(
209 &self,
210 paths: impl IntoIterator<Item = S>,
211 ) -> mlua::Result<()> {
212 let new = paths
213 .into_iter()
214 .map(|v| v.as_ref().display().to_string())
215 .collect::<Vec<_>>()
216 .join(";");
217 let lua_path = match self.path()?.trim() {
218 "" => new,
219 other => format!("{new};{other}"),
220 };
221 self.globals()
222 .get::<Table>("package")?
223 .set("path", lua_path)
224 }
225
226 fn append_path<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
227 let lua_path = match self.path()?.trim() {
228 "" => path.as_ref().display().to_string(),
229 other => format!("{other};{}", path.as_ref().display()),
230 };
231 self.globals()
232 .get::<Table>("package")?
233 .set("path", lua_path)
234 }
235
236 fn append_paths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()> {
237 let new = paths
238 .into_iter()
239 .map(|v| v.as_ref().display().to_string())
240 .collect::<Vec<_>>()
241 .join(";");
242 let lua_path = match self.path()?.trim() {
243 "" => new,
244 other => format!("{other};{new}"),
245 };
246 self.globals()
247 .get::<Table>("package")?
248 .set("path", lua_path)
249 }
250
251 fn set_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
252 self.globals()
253 .get::<Table>("package")
254 .unwrap()
255 .set("cpath", path.as_ref().display().to_string())
256 }
257
258 fn set_cpaths<S: AsRef<Path>>(&self, paths: impl IntoIterator<Item = S>) -> mlua::Result<()> {
259 self.globals().get::<Table>("package").unwrap().set(
260 "cpath",
261 paths
262 .into_iter()
263 .map(|s| s.as_ref().display().to_string())
264 .collect::<Vec<_>>()
265 .join(";"),
266 )
267 }
268
269 fn prepend_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
270 let lua_path = match self.path()?.trim() {
271 "" => path.as_ref().display().to_string(),
272 other => format!("{};{other}", path.as_ref().display()),
273 };
274 self.globals()
275 .get::<Table>("package")?
276 .set("cpath", lua_path)
277 }
278
279 fn prepend_cpaths<S: AsRef<Path>>(
280 &self,
281 paths: impl IntoIterator<Item = S>,
282 ) -> mlua::Result<()> {
283 let new = paths
284 .into_iter()
285 .map(|v| v.as_ref().display().to_string())
286 .collect::<Vec<_>>()
287 .join(";");
288 let lua_path = match self.path()?.trim() {
289 "" => new,
290 other => format!("{new};{other}"),
291 };
292 self.globals()
293 .get::<Table>("package")?
294 .set("cpath", lua_path)
295 }
296
297 fn append_cpath<S: AsRef<Path>>(&self, path: S) -> mlua::Result<()> {
298 let lua_path = match self.cpath()?.trim() {
299 "" => path.as_ref().display().to_string(),
300 other => format!("{other};{}", path.as_ref().display()),
301 };
302 self.globals()
303 .get::<Table>("package")?
304 .set("cpath", lua_path)
305 }
306
307 fn append_cpaths<S: AsRef<Path>>(
308 &self,
309 paths: impl IntoIterator<Item = S>,
310 ) -> mlua::Result<()> {
311 let new = paths
312 .into_iter()
313 .map(|v| v.as_ref().display().to_string())
314 .collect::<Vec<_>>()
315 .join(";");
316 let lua_path = match self.path()?.trim() {
317 "" => new,
318 other => format!("{other};{new}"),
319 };
320 self.globals()
321 .get::<Table>("package")?
322 .set("cpath", lua_path)
323 }
324}
325
326pub trait UserDataGetSet<T> {
328 fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
330 where
331 S: Into<String>,
332 R: IntoLua,
333 A: FromLua,
334 GET: 'static + MaybeSend + Fn(&Lua, &T) -> mlua::Result<R>,
335 SET: 'static + MaybeSend + Fn(&Lua, &mut T, A) -> mlua::Result<()>;
336
337 fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
339 where
340 S: Into<String>,
341 R: IntoLua,
342 A: FromLua,
343 GET: 'static + MaybeSend + Fn(&Lua, AnyUserData) -> mlua::Result<R>,
344 SET: 'static + MaybeSend + Fn(&Lua, AnyUserData, A) -> mlua::Result<()>;
345}
346
347impl<T, U: UserDataFields<T>> UserDataGetSet<T> for U {
348 fn add_field_method_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
349 where
350 S: Into<String>,
351 R: IntoLua,
352 A: FromLua,
353 GET: Fn(&Lua, &T) -> mlua::Result<R> + MaybeSend + 'static,
354 SET: Fn(&Lua, &mut T, A) -> mlua::Result<()> + MaybeSend + 'static,
355 {
356 let name: String = name.into();
357 self.add_field_method_get(&name, get);
358 self.add_field_method_set(name, set);
359 }
360
361 fn add_field_function_get_set<S, R, A, GET, SET>(&mut self, name: S, get: GET, set: SET)
362 where
363 S: Into<String>,
364 R: IntoLua,
365 A: FromLua,
366 GET: Fn(&Lua, AnyUserData) -> mlua::Result<R> + MaybeSend + 'static,
367 SET: Fn(&Lua, AnyUserData, A) -> mlua::Result<()> + MaybeSend + 'static,
368 {
369 let name: String = name.into();
370 self.add_field_function_get(&name, get);
371 self.add_field_function_set(name, set);
372 }
373}