1use lua::{State, Index, ToLua, FromLua, Function, REGISTRYINDEX};
2use types;
3use std::ptr;
4use error;
5
6pub struct Context<'a> {
11 state: &'a mut State,
12 target_pos: Index,
13}
14
15pub fn userdata_drop<T>(state: &mut State) -> i32 {
17 use std::ptr;
18 let mut context = Context::new(state);
19 unsafe {
20 let userdata = context.get_arg_typed::<types::LuaUserdata>(1).unwrap();
22 let entity = userdata.get_value::<T>(&mut context).unwrap();
23 ptr::drop_in_place(entity as *mut T);
24 };
25 0
26}
27
28impl<'a> Context<'a> {
29 pub fn new(state: &mut State) -> Context {
31 let pos = state.get_top();
32 Context {
33 state: state,
34 target_pos: pos,
35 }
36 }
37
38 pub fn get_state(&mut self) -> &mut State {
40 self.state
41 }
42
43 pub fn push_number(&mut self, value: f64) -> types::LuaNumber {
45 self.state.push_number(value);
46 let i = self.state.get_top();
47 types::LuaNumber::new(i)
48 }
49
50 pub fn push_string(&mut self, value: &str) -> types::LuaString {
52 self.state.push_string(value);
53 let i = self.state.get_top();
54 types::LuaString::new(i)
55 }
56
57 pub fn push_table(&mut self) -> types::LuaTable {
59 self.state.new_table();
60 let i = self.state.get_top();
61 types::LuaTable::new(i)
62 }
63
64 pub fn push_bool(&mut self, value: bool) -> types::LuaBool {
66 self.state.push_bool(value);
67 let i = self.state.get_top();
68 types::LuaBool::new(i)
69 }
70
71 pub fn push_function(&mut self, func: Function) -> types::LuaFunction {
73 self.state.push_fn(func);
74 let i = self.state.get_top();
75 types::LuaFunction::new(i)
76 }
77
78 pub fn push_integer(&mut self, value: i64) -> types::LuaInteger {
80 self.state.push_integer(value);
81 let i = self.state.get_top();
82 types::LuaInteger::new(i)
83 }
84
85 pub fn push_nil(&mut self) -> types::LuaNil {
87 self.state.push_nil();
88 let i = self.state.get_top();
89 types::LuaNil::new(i)
90 }
91
92 pub fn push_userdata<T>(&mut self, value: T) -> types::LuaUserdata {
94 unsafe { ptr::write(self.state.new_userdata_typed(), value); }
95 let i = self.state.get_top();
96 types::LuaUserdata::new(i)
97 }
98
99 pub fn push_userdata_named<T>(&mut self, value: T, name: &str) -> types::LuaUserdata {
101 let entity_object = self.push_userdata(value);
102 let entity_object_meta = self.metatable_get(&name).unwrap();
103 entity_object.set_metatable(self, &entity_object_meta);
104 entity_object
105 }
106
107 pub fn push_thread(&mut self) -> types::LuaThread {
112 self.state.new_thread();
113 let i = self.state.get_top();
114 types::LuaThread::new(i)
115 }
116
117 pub fn create_lib(&mut self, lib: &[(&str, Function)]) -> types::LuaTable {
119 self.state.new_lib(lib);
120 let i = self.state.get_top();
121 types::LuaTable::new(i)
122 }
123
124 pub fn push_global(&mut self, key: &str) -> types::LuaGeneric {
126 self.state.get_global(key);
127 let i = self.state.get_top();
128 types::LuaGeneric::new(i)
129 }
130
131 pub fn set_global(&mut self, key: &str, value: &ToLua) {
133 value.to_lua(self.state);
134 self.state.set_global(key);
135 }
136
137 pub fn get_from_registry(&mut self, key: &ToLua) -> types::LuaGeneric {
139 key.to_lua(self.state);
140 self.state.get_table(REGISTRYINDEX);
141 let i = self.state.get_top();
142 types::LuaGeneric::new(i)
143 }
144
145 pub fn get_from_registry_typed<T: FromLua>(&mut self, key: &ToLua) -> Option<T> {
147 key.to_lua(self.state);
148 self.state.get_table(REGISTRYINDEX);
149 let i = self.state.get_top();
150 T::from_lua(&mut self.state, i)
151 }
152
153 pub fn set_in_registry(&mut self, key: &ToLua, value: &ToLua) {
155 key.to_lua(self.state);
156 value.to_lua(self.state);
157 self.state.set_table(REGISTRYINDEX);
158 }
159
160 pub fn get_arg(&mut self, arg: Index) -> Option<types::LuaGeneric> {
162 if self.state.is_none(arg) {
163 None
164 } else {
165 Some(types::LuaGeneric::new(arg))
166 }
167 }
168
169 pub fn get_arg_typed<T: FromLua>(&mut self, arg: Index) -> Option<T> {
171 T::from_lua(&mut self.state, arg)
172 }
173
174 pub fn get_arg_typed_or<T: FromLua>(&mut self, arg: Index, value: T) -> Option<T> {
178 if self.state.is_none_or_nil(arg) {
179 Some(value)
180 } else {
181 T::from_lua(&mut self.state, arg)
182 }
183 }
184
185 pub fn do_string(&mut self, s: &str) -> error::Result<()> {
191 let threadstatus = self.state.do_string(&s);
192 match error::get_status_from_threadstatus(threadstatus) {
193 Ok(_) => {
194 error::new_luaresult_ok(())
195 },
196 Err(status) => {
197 error::new_luaresult_err(status, error::pop_error_from_state(&mut self.state))
198 }
199 }
200 }
201
202 pub fn push_context(&mut self) -> Context {
207 Context::new(&mut self.state)
208 }
209
210 pub fn return_context(mut self, args: &[&ToLua]) -> Index {
212 for arg in args.iter().rev() {
214 arg.to_lua(&mut self.state);
215 }
216 for i in 0..args.len() {
217 self.state.replace(i as Index + self.target_pos);
218 }
219 self.target_pos += args.len() as Index;
220 args.len() as Index
221 }
222
223 pub fn metatable_register(&mut self, name: &str) -> (bool, types::LuaTable) {
228 let ret = self.state.new_metatable(name);
229 let i = self.state.get_top();
230 let table = types::LuaTable::new(i);
231 (ret, table)
232 }
233
234 pub fn metatable_get(&mut self, name: &str) -> Option<types::LuaTable> {
236 self.state.get_metatable_from_registry(name);
237 match self.state.is_table(-1) {
238 true => {
239 let i = self.state.get_top();
240 let table = types::LuaTable::new(i);
241 Some(table)
242 },
243 false => {
244 self.state.pop(1);
245 None
246 }
247 }
248 }
249
250 pub fn metatable_register_named<T>(&mut self, lib: &[(&str, Function)], metamethods: &[(&str, Function)], unique_name: &str)
255 -> Option<types::LuaTable> {
256 let entity_library_members = self.create_lib(lib);
257 let (should_set, entity_metatable) = self.metatable_register(unique_name);
258 if should_set {
259 for &(ref name, ref value) in metamethods.iter() {
260 entity_metatable.set_raw(self, name, value);
261 }
262 entity_metatable.set_raw(self, &"__index", &entity_library_members);
263 entity_metatable.set_raw(self, &"__gc", &lua_func!(userdata_drop<T>));
264 entity_metatable.set_raw(self, &"__metatable", &0);
266 }
267 Some(entity_metatable)
268 }
269}
270
271impl<'a> Drop for Context<'a> {
272 fn drop(&mut self) {
273 self.state.set_top(self.target_pos);
274 }
275}