push_trait/
push_trait.rs

1//! Example of extending `Thread` to add an overloaded `push` method.
2
3use core::ffi::CStr;
4use lunka::prelude::*;
5
6const PRINT_CODE: &str = r#"print("Received arguments: ", ...)"#;
7
8const PRINT_CODE_LUA_NAME: &CStr = c"=<embedded>";
9
10trait Push<const N: usize> {
11	fn push_into(&self, thread: &LuaThread);
12}
13
14impl Push<1> for ()  {
15	fn push_into(&self, thread: &LuaThread) {
16		thread.push_nil();
17	}
18}
19
20impl Push<1> for LuaInteger {
21	fn push_into(&self, thread: &LuaThread) {
22		thread.push_integer(*self);
23	}
24}
25
26impl Push<1> for LuaNumber {
27	fn push_into(&self, thread: &LuaThread) {
28		thread.push_number(*self);
29	}
30}
31
32impl Push<1> for &str {
33	fn push_into(&self, thread: &LuaThread) {
34		thread.push_string(self.as_bytes());
35	}
36}
37
38impl<T: Push<1>, E: Push<1>> Push<2> for Result<T, E> {
39	fn push_into(&self, thread: &LuaThread) {
40		match self {
41			Self::Ok(t) => {
42				t.push_into(thread);
43				thread.push_nil()
44			}
45			Self::Err(e) => {
46				thread.push_fail();
47				e.push_into(thread)
48			}
49		}
50	}
51}
52
53trait LuaThreadExt {
54	fn push<const N: usize>(&self, what: impl Push<N>);
55}
56
57impl LuaThreadExt for LuaThread {
58	fn push<const N: usize>(&self, what: impl Push<N>) {
59		what.push_into(self)
60	}
61}
62
63fn main() {
64	let mut lua = Lua::new();
65	lua.run_managed(|mut mg| mg.open_libs());
66
67	if !lua.load_string(PRINT_CODE.as_bytes(), PRINT_CODE_LUA_NAME).is_ok() {
68		panic!("couldn't load Lua chunk");
69	}
70
71	lua.push(4 as LuaInteger);
72	lua.push(3.1 as LuaNumber);
73	lua.push("how");
74
75	if !lua.run_managed(|mut mg| {
76		mg.restart_gc();
77		unsafe { mg.pcall(3, 0, 0) }
78	}).is_ok() {
79		let error_bytes = lua.to_string(-1);
80		panic!(
81			"error while running Lua chunk: {}",
82			error_bytes.map(String::from_utf8_lossy)
83				.unwrap_or(std::borrow::Cow::Borrowed("<no message>"))
84		);
85	}
86}