hlua_badtouch/lib.rs
1//! High-level zero-cost bindings for Lua
2//!
3//! Lua is an interpreted programming language. This crate allows you to execute Lua code.
4//!
5//! # General usage
6//!
7//! In order to execute Lua code you first need a *Lua context*, which is represented in this
8//! library with [the `Lua` struct](struct.Lua.html). You can then call
9//! [the `execute` method](struct.Lua.html#method.execute) on this object.
10//!
11//! For example:
12//!
13//! ```
14//! use hlua::Lua;
15//!
16//! let mut lua = Lua::new();
17//! lua.execute::<()>("a = 12 * 5").unwrap();
18//! ```
19//!
20//! This example puts the value `60` in the global variable `a`. The values of all global variables
21//! are stored within the `Lua` struct. If you execute multiple Lua scripts on the same context,
22//! each script will have access to the same global variables that were modified by the previous
23//! scripts.
24//!
25//! In order to do something actually useful with Lua, we will need to make Lua and Rust
26//! communicate with each other. This can be done in four ways:
27//!
28//! - You can use methods on the `Lua` struct to read or write the values of global variables with
29//! the [`get`](struct.Lua.html#method.get) and [`set`](struct.Lua.html#method.set) methods. For
30//! example you can write to a global variable with a Lua script then read it from Rust, or you
31//! can write to a global variable from Rust then read it from a Lua script.
32//!
33//! - The Lua script that you execute with the [`execute`](struct.Lua.html#method.execute) method
34//! can return a value.
35//!
36//! - You can set the value of a global variable to a Rust functions or closures, which can then be
37//! invoked with a Lua script. See [the `Function` struct](struct.Function.html) for more
38//! information. For example if you set the value of the global variable `foo` to a Rust
39//! function, you can then call it from Lua with `foo()`.
40//!
41//! - Similarly you can set the value of a global variable to a Lua function, then call it from
42//! Rust. The function call can return a value.
43//!
44//! Which method(s) you use depends on which API you wish to expose to your Lua scripts.
45//!
46//! # Pushing and loading values
47//!
48//! The interface between Rust and Lua involves two things:
49//!
50//! - Sending values from Rust to Lua, which is known as *pushing* the value.
51//! - Sending values from Lua to Rust, which is known as *loading* the value.
52//!
53//! Pushing (ie. sending from Rust to Lua) can be done with
54//! [the `set` method](struct.Lua.html#method.set):
55//!
56//! ```
57//! # use hlua::Lua;
58//! # let mut lua = Lua::new();
59//! lua.set("a", 50);
60//! ```
61//!
62//! You can push values that implement [the `Push` trait](trait.Push.html) or
63//! [the `PushOne` trait](trait.PushOne.html) depending on the situation:
64//!
65//! - Integers, floating point numbers and booleans.
66//! - `String` and `&str`.
67//! - Any Rust function or closure whose parameters and loadable and whose return type is pushable.
68//! See the documentation of [the `Function` struct](struct.Function.html) for more information.
69//! - [The `AnyLuaValue` struct](struct.AnyLuaValue.html). This enumeration represents any possible
70//! value in Lua.
71//! - The [`LuaCode`](struct.LuaCode.html) and
72//! [`LuaCodeFromReader`](struct.LuaCodeFromReader.html) structs. Since pushing these structs can
73//! result in an error, you need to use [`checked_set`](struct.Lua.html#method.checked_set)
74//! instead of `set`.
75//! - `Vec`s and `HashMap`s whose content is pushable.
76//! - As a special case, `Result` can be pushed only as the return type of a Rust function or
77//! closure. If they contain an error, the Rust function call is considered to have failed.
78//! - As a special case, tuples can be pushed when they are the return type of a Rust function or
79//! closure. They implement `Push` but not `PushOne`.
80//! - TODO: userdata
81//!
82//! Loading (ie. sending from Lua to Rust) can be done with
83//! [the `get` method](struct.Lua.html#method.get):
84//!
85//! ```no_run
86//! # use hlua::Lua;
87//! # let mut lua = Lua::new();
88//! let a: i32 = lua.get("a").unwrap();
89//! ```
90//!
91//! You can load values that implement [the `LuaRead` trait](trait.LuaRead.html):
92//!
93//! - Integers, floating point numbers and booleans.
94//! - `String` and [`StringInLua`](struct.StringInLua.html) (ie. the equivalent of `&str`). Loading
95//! the latter has no cost while loading a `String` performs an allocation.
96//! - Any function (Lua or Rust), with [the `LuaFunction` struct](struct.LuaFunction.html). This
97//! can then be used to execute the function.
98//! - [The `AnyLuaValue` struct](struct.AnyLuaValue.html). This enumeration represents any possible
99//! value in Lua.
100//! - [The `LuaTable` struct](struct.LuaTable.html). This struct represents a table in Lua, where
101//! keys and values can be of different types. The table can then be iterated and individual
102//! elements can be loaded or modified.
103//! - As a special case, tuples can be loaded when they are the return type of a Lua function or as
104//! the return type of [`execute`](struct.Lua.html#method.execute).
105//! - TODO: userdata
106//!
107
108// Export the version of lua52_sys in use by this crate. This allows clients to perform low-level
109// Lua operations without worrying about semver.
110#[doc(hidden)]
111pub extern crate lua52_sys as ffi;
112extern crate libc;
113
114use std::ffi::{CStr, CString};
115use std::io::Read;
116use std::io::Error as IoError;
117use std::borrow::Borrow;
118use std::marker::PhantomData;
119use std::error::Error;
120use std::fmt;
121use std::convert::From;
122use std::io;
123
124pub use any::{AnyHashableLuaValue, AnyLuaString, AnyLuaValue};
125pub use functions_write::{Function, InsideCallback};
126pub use functions_write::{function0, function1, function2, function3, function4, function5};
127pub use functions_write::{function6, function7, function8, function9, function10};
128pub use lua_functions::LuaFunction;
129pub use lua_functions::LuaFunctionCallError;
130pub use lua_functions::{LuaCode, LuaCodeFromReader};
131pub use lua_tables::LuaTable;
132pub use lua_tables::LuaTableIterator;
133pub use tuples::TuplePushError;
134pub use userdata::UserdataOnStack;
135pub use userdata::{push_userdata, read_userdata};
136pub use values::StringInLua;
137
138mod any;
139mod functions_write;
140mod lua_functions;
141mod lua_tables;
142mod macros;
143mod rust_tables;
144mod userdata;
145mod values;
146mod tuples;
147
148/// Main object of the library.
149///
150/// The lifetime parameter corresponds to the lifetime of the content of the Lua context.
151///
152/// # About panic safety
153///
154/// This type isn't panic safe. This means that if a panic happens while you were using the `Lua`,
155/// then it will probably stay in a corrupt state. Trying to use the `Lua` again will most likely
156/// result in another panic but shouldn't result in unsafety.
157#[derive(Debug)]
158pub struct Lua<'lua> {
159 lua: LuaContext,
160 must_be_closed: bool,
161 marker: PhantomData<&'lua ()>,
162}
163
164/// RAII guard for a value pushed on the stack.
165///
166/// You shouldn't have to manipulate this type directly unless you are fiddling with the
167/// library's internals.
168#[derive(Debug)]
169pub struct PushGuard<L> {
170 lua: L,
171 size: i32,
172 raw_lua: LuaContext,
173}
174
175impl<'lua, L> PushGuard<L>
176 where L: AsMutLua<'lua>
177{
178 /// Creates a new `PushGuard` from this Lua context representing `size` items on the stack.
179 /// When this `PushGuard` is destroyed, `size` items will be popped.
180 ///
181 /// This is unsafe because the Lua stack can be corrupted if this is misused.
182 #[inline]
183 pub unsafe fn new(mut lua: L, size: i32) -> Self {
184 let raw_lua = lua.as_mut_lua();
185 PushGuard {
186 lua,
187 size,
188 raw_lua,
189 }
190 }
191
192 #[inline]
193 fn assert_one_and_forget(self) -> i32 {
194 assert_eq!(self.size, 1);
195 self.forget_internal()
196 }
197
198 /// Returns the number of elements managed by this `PushGuard`.
199 #[inline]
200 pub fn size(&self) -> i32 {
201 self.size
202 }
203
204 /// Prevents the value from being popped when the `PushGuard` is destroyed, and returns the
205 /// number of elements on the Lua stack.
206 ///
207 /// This is unsafe because the Lua stack can be corrupted if this is misused.
208 #[inline]
209 pub unsafe fn forget(self) -> i32 {
210 self.forget_internal()
211 }
212
213 /// Internal crate-only version of `forget`. It is generally assumed that code within this
214 /// crate that calls this method knows what it is doing.
215 #[inline]
216 fn forget_internal(mut self) -> i32 {
217 let size = self.size;
218 self.size = 0;
219 size
220 }
221
222 /// Destroys the guard, popping the value. Returns the inner part,
223 /// which returns access when using by-value capture.
224 #[inline]
225 pub fn into_inner(mut self) -> L {
226 use std::{mem, ptr};
227
228 let mut res;
229 unsafe {
230 res = mem::uninitialized();
231 ptr::copy_nonoverlapping(&self.lua, &mut res, 1);
232 if self.size != 0 {
233 ffi::lua_pop(self.lua.as_mut_lua().0, self.size);
234 }
235 };
236 mem::forget(self);
237
238 res
239 }
240}
241
242/// Trait for objects that have access to a Lua context. When using a context returned by a
243/// `AsLua`, you are not allowed to modify the stack.
244// TODO: the lifetime should be an associated lifetime instead
245pub unsafe trait AsLua<'lua> {
246 fn as_lua(&self) -> LuaContext;
247}
248
249/// Trait for objects that have access to a Lua context. You are allowed to modify the stack, but
250/// it must be in the same state as it was when you started.
251// TODO: the lifetime should be an associated lifetime instead
252pub unsafe trait AsMutLua<'lua>: AsLua<'lua> {
253 /// Returns the raw Lua context.
254 fn as_mut_lua(&mut self) -> LuaContext;
255}
256
257/// Opaque type that contains the raw Lua context.
258// TODO: probably no longer necessary
259#[derive(Copy, Clone, Debug)]
260pub struct LuaContext(*mut ffi::lua_State);
261
262impl LuaContext {
263 /// Return a pointer to the inner `lua_State` for this context. This is an escape hatch that
264 /// lets the caller perform arbitrary operations against the FFI directly.
265 ///
266 /// Be careful: performing operations on this state might invalidate assumptions made in
267 /// higher-level APIs. For example, pushing a value onto the Lua stack will cause `PushGuard`s
268 /// in Rust code to be out of sync with the Lua stack.
269 #[doc(hidden)]
270 #[inline]
271 pub fn state_ptr(&self) -> *mut ffi::lua_State {
272 self.0
273 }
274}
275
276unsafe impl Send for LuaContext {}
277
278unsafe impl<'a, 'lua> AsLua<'lua> for Lua<'lua> {
279 #[inline]
280 fn as_lua(&self) -> LuaContext {
281 self.lua
282 }
283}
284
285unsafe impl<'lua> AsMutLua<'lua> for Lua<'lua> {
286 #[inline]
287 fn as_mut_lua(&mut self) -> LuaContext {
288 self.lua
289 }
290}
291
292unsafe impl<'lua, L> AsLua<'lua> for PushGuard<L>
293 where L: AsMutLua<'lua>
294{
295 #[inline]
296 fn as_lua(&self) -> LuaContext {
297 self.lua.as_lua()
298 }
299}
300
301unsafe impl<'lua, L> AsMutLua<'lua> for PushGuard<L>
302 where L: AsMutLua<'lua>
303{
304 #[inline]
305 fn as_mut_lua(&mut self) -> LuaContext {
306 self.lua.as_mut_lua()
307 }
308}
309
310unsafe impl<'a, 'lua, L: ?Sized> AsLua<'lua> for &'a L
311 where L: AsLua<'lua>
312{
313 #[inline]
314 fn as_lua(&self) -> LuaContext {
315 (**self).as_lua()
316 }
317}
318
319unsafe impl<'a, 'lua, L: ?Sized> AsLua<'lua> for &'a mut L
320 where L: AsLua<'lua>
321{
322 #[inline]
323 fn as_lua(&self) -> LuaContext {
324 (**self).as_lua()
325 }
326}
327
328unsafe impl<'a, 'lua, L: ?Sized> AsMutLua<'lua> for &'a mut L
329 where L: AsMutLua<'lua>
330{
331 #[inline]
332 fn as_mut_lua(&mut self) -> LuaContext {
333 (**self).as_mut_lua()
334 }
335}
336
337/// Types that can be given to a Lua context, for example with `lua.set()` or as a return value
338/// of a function.
339pub trait Push<L> {
340 /// Error that can happen when pushing a value.
341 type Err;
342
343 /// Pushes the value on the top of the stack.
344 ///
345 /// Must return a guard representing the elements that have been pushed.
346 ///
347 /// You can implement this for any type you want by redirecting to call to
348 /// another implementation (for example `5.push_to_lua`) or by calling
349 /// `userdata::push_userdata`.
350 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)>;
351
352 /// Same as `push_to_lua` but can only succeed and is only available if `Err` is `Void`.
353 // TODO: when https://github.com/rust-lang/rust/issues/20041 is fixed, use `Self::Err == Void`
354 #[inline]
355 fn push_no_err<E>(self, lua: L) -> PushGuard<L>
356 where Self: Sized,
357 Self: Push<L, Err = E>,
358 E: Into<Void>,
359 {
360 match self.push_to_lua(lua) {
361 Ok(p) => p,
362 Err(_) => unreachable!(),
363 }
364 }
365}
366
367/// Extension trait for `Push`. Guarantees that only one element will be pushed.
368///
369/// This should be implemented on most types that implement `Push`, except for tuples.
370///
371/// > **Note**: Implementing this trait on a type that pushes multiple elements will most likely
372/// > result in panics.
373// Note for the implementation: since this trait is not unsafe, it is mostly a hint. Functions can
374// require this trait if they only accept one pushed element, but they must also add a runtime
375// assertion to make sure that only one element was actually pushed.
376pub trait PushOne<L>: Push<L> {}
377
378/// Type that cannot be instantiated.
379///
380/// Will be replaced with `!` eventually (https://github.com/rust-lang/rust/issues/35121).
381#[derive(Debug, Copy, Clone)]
382pub enum Void {}
383
384impl fmt::Display for Void {
385 fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
386 unreachable!("Void cannot be instantiated")
387 }
388}
389
390/// Types that can be obtained from a Lua context.
391///
392/// Most types that implement `Push` also implement `LuaRead`, but this is not always the case
393/// (for example `&'static str` implements `Push` but not `LuaRead`).
394pub trait LuaRead<L>: Sized {
395 /// Reads the data from Lua.
396 #[inline]
397 fn lua_read(lua: L) -> Result<Self, L> {
398 LuaRead::lua_read_at_position(lua, -1)
399 }
400
401 /// Reads the data from Lua at a given position.
402 fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L>;
403}
404
405/// Error that can happen when executing Lua code.
406#[derive(Debug)]
407pub enum LuaError {
408 /// There was a syntax error when parsing the Lua code.
409 SyntaxError(String),
410
411 /// There was an error during execution of the Lua code
412 /// (for example not enough parameters for a function call).
413 ExecutionError(String),
414
415 /// There was an IoError while reading the source code to execute.
416 ReadError(IoError),
417
418 /// The call to `execute` has requested the wrong type of data.
419 WrongType,
420}
421
422impl fmt::Display for LuaError {
423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
424 use LuaError::*;
425
426 match *self {
427 SyntaxError(ref s) => write!(f, "Syntax error: {}", s),
428 ExecutionError(ref s) => write!(f, "Execution error: {}", s),
429 ReadError(ref e) => write!(f, "Read error: {}", e),
430 WrongType => write!(f, "Wrong type returned by Lua"),
431 }
432 }
433}
434
435impl Error for LuaError {
436 fn description(&self) -> &str {
437 use LuaError::*;
438
439 match *self {
440 SyntaxError(ref s) => &s,
441 ExecutionError(ref s) => &s,
442 ReadError(_) => "read error",
443 WrongType => "wrong type returned by Lua",
444 }
445 }
446
447 fn cause(&self) -> Option<&Error> {
448 use LuaError::*;
449
450 match *self {
451 SyntaxError(_) => None,
452 ExecutionError(_) => None,
453 ReadError(ref e) => Some(e),
454 WrongType => None,
455 }
456 }
457}
458
459impl From<io::Error> for LuaError {
460 fn from(e: io::Error) -> Self {
461 LuaError::ReadError(e)
462 }
463}
464
465impl<'lua> Lua<'lua> {
466 /// Builds a new empty Lua context.
467 ///
468 /// There are no global variables and the registry is totally empty. Even the functions from
469 /// the standard library can't be used.
470 ///
471 /// If you want to use the Lua standard library in the scripts of this context, see
472 /// [the openlibs method](#method.openlibs)
473 ///
474 /// # Example
475 ///
476 /// ```
477 /// use hlua::Lua;
478 /// let mut lua = Lua::new();
479 /// ```
480 ///
481 /// # Panic
482 ///
483 /// The function panics if the underlying call to `lua_newstate` fails
484 /// (which indicates lack of memory).
485 #[inline]
486 pub fn new() -> Lua<'lua> {
487 let lua = unsafe { ffi::lua_newstate(alloc, std::ptr::null_mut()) };
488 if lua.is_null() {
489 panic!("lua_newstate failed");
490 }
491
492 // this alloc function is required to create a lua state.
493 extern "C" fn alloc(_ud: *mut libc::c_void,
494 ptr: *mut libc::c_void,
495 _osize: libc::size_t,
496 nsize: libc::size_t)
497 -> *mut libc::c_void {
498 unsafe {
499 if nsize == 0 {
500 libc::free(ptr as *mut libc::c_void);
501 std::ptr::null_mut()
502 } else {
503 libc::realloc(ptr, nsize)
504 }
505 }
506 }
507
508 // called whenever lua encounters an unexpected error.
509 extern "C" fn panic(lua: *mut ffi::lua_State) -> libc::c_int {
510 let err = unsafe { ffi::lua_tostring(lua, -1) };
511 let err = unsafe { CStr::from_ptr(err) };
512 let err = String::from_utf8(err.to_bytes().to_vec()).unwrap();
513 panic!("PANIC: unprotected error in call to Lua API ({})\n", err);
514 }
515
516 unsafe { ffi::lua_atpanic(lua, panic) };
517
518 Lua {
519 lua: LuaContext(lua),
520 must_be_closed: true,
521 marker: PhantomData,
522 }
523 }
524
525 /// Takes an existing `lua_State` and build a Lua object from it.
526 ///
527 /// If `close_at_the_end` is true, `lua_close` will be called on the `lua_State` in the
528 /// destructor.
529 #[inline]
530 pub unsafe fn from_existing_state<T>(lua: *mut T, close_at_the_end: bool) -> Lua<'lua> {
531 Lua {
532 lua: std::mem::transmute(lua),
533 must_be_closed: close_at_the_end,
534 marker: PhantomData,
535 }
536 }
537
538 /// Opens all standard Lua libraries.
539 ///
540 /// See the reference for the standard library here:
541 /// https://www.lua.org/manual/5.2/manual.html#6
542 ///
543 /// This is done by calling `luaL_openlibs`.
544 ///
545 /// # Example
546 ///
547 /// ```
548 /// use hlua::Lua;
549 /// let mut lua = Lua::new();
550 /// lua.openlibs();
551 /// ```
552 #[inline]
553 pub fn openlibs(&mut self) {
554 unsafe { ffi::luaL_openlibs(self.lua.0) }
555 }
556
557 /// Opens base library.
558 ///
559 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_base
560 #[inline]
561 pub fn open_base(&mut self) {
562 unsafe { ffi::luaopen_base(self.lua.0) }
563 }
564
565 /// Opens bit32 library.
566 ///
567 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_bit32
568 #[inline]
569 pub fn open_bit32(&mut self) {
570 unsafe { ffi::luaopen_bit32(self.lua.0) }
571 }
572
573 /// Opens coroutine library.
574 ///
575 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_coroutine
576 #[inline]
577 pub fn open_coroutine(&mut self) {
578 unsafe { ffi::luaopen_coroutine(self.lua.0) }
579 }
580
581 /// Opens debug library.
582 ///
583 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_debug
584 #[inline]
585 pub fn open_debug(&mut self) {
586 unsafe { ffi::luaopen_debug(self.lua.0) }
587 }
588
589 /// Opens io library.
590 ///
591 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_io
592 #[inline]
593 pub fn open_io(&mut self) {
594 unsafe { ffi::luaopen_io(self.lua.0) }
595 }
596
597 /// Opens math library.
598 ///
599 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_math
600 #[inline]
601 pub fn open_math(&mut self) {
602 unsafe { ffi::luaopen_math(self.lua.0) }
603 }
604
605 /// Opens os library.
606 ///
607 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_os
608 #[inline]
609 pub fn open_os(&mut self) {
610 unsafe { ffi::luaopen_os(self.lua.0) }
611 }
612
613 /// Opens package library.
614 ///
615 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_package
616 #[inline]
617 pub fn open_package(&mut self) {
618 unsafe { ffi::luaopen_package(self.lua.0) }
619 }
620
621 /// Opens string library.
622 ///
623 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_string
624 #[inline]
625 pub fn open_string(&mut self) {
626 unsafe { ffi::luaopen_string(self.lua.0) }
627 }
628
629 /// Opens table library.
630 ///
631 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_table
632 #[inline]
633 pub fn open_table(&mut self) {
634 unsafe { ffi::luaopen_table(self.lua.0) }
635 }
636
637 /// Executes some Lua code in the context.
638 ///
639 /// The code will have access to all the global variables you set with methods such as `set`.
640 /// Every time you execute some code in the context, the code can modify these global variables.
641 ///
642 /// The template parameter of this function is the return type of the expression that is being
643 /// evaluated.
644 /// In order to avoid compilation error, you should call this function either by doing
645 /// `lua.execute::<T>(...)` or `let result: T = lua.execute(...);` where `T` is the type of
646 /// the expression.
647 /// The function will return an error if the actual return type of the expression doesn't
648 /// match the template parameter.
649 ///
650 /// The return type must implement the `LuaRead` trait. See
651 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
652 /// information.
653 ///
654 /// # Examples
655 ///
656 /// Without a return value:
657 ///
658 /// ```
659 /// use hlua::Lua;
660 /// let mut lua = Lua::new();
661 /// lua.execute::<()>("function multiply_by_two(a) return a * 2 end").unwrap();
662 /// lua.execute::<()>("twelve = multiply_by_two(6)").unwrap();
663 /// ```
664 ///
665 /// With a return value:
666 ///
667 /// ```
668 /// use hlua::Lua;
669 /// let mut lua = Lua::new();
670 ///
671 /// let twelve: i32 = lua.execute("return 3 * 4;").unwrap();
672 /// let sixty = lua.execute::<i32>("return 6 * 10;").unwrap();
673 /// ```
674 #[inline]
675 pub fn execute<'a, T>(&'a mut self, code: &str) -> Result<T, LuaError>
676 where T: for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>
677 {
678 let mut f = try!(lua_functions::LuaFunction::load(self, code));
679 f.call()
680 }
681
682 /// Executes some Lua code on the context.
683 ///
684 /// This does the same thing as [the `execute` method](#method.execute), but the code to
685 /// execute is loaded from an object that implements `Read`.
686 ///
687 /// Use this method when you potentially have a large amount of code (for example if you read
688 /// the code from a file) in order to avoid having to put everything in memory first before
689 /// passing it to the Lua interpreter.
690 ///
691 /// # Example
692 ///
693 /// ```no_run
694 /// use std::fs::File;
695 /// use hlua::Lua;
696 ///
697 /// let mut lua = Lua::new();
698 /// let script = File::open("script.lua").unwrap();
699 /// lua.execute_from_reader::<(), _>(script).unwrap();
700 /// ```
701 #[inline]
702 pub fn execute_from_reader<'a, T, R>(&'a mut self, code: R) -> Result<T, LuaError>
703 where T: for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>,
704 R: Read
705 {
706 let mut f = try!(lua_functions::LuaFunction::load_from_reader(self, code));
707 f.call()
708 }
709
710 /// Reads the value of a global variable.
711 ///
712 /// Returns `None` if the variable doesn't exist or has the wrong type.
713 ///
714 /// The type must implement the `LuaRead` trait. See
715 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
716 /// information.
717 ///
718 /// # Example
719 ///
720 /// ```
721 /// use hlua::Lua;
722 /// let mut lua = Lua::new();
723 /// lua.execute::<()>("a = 5").unwrap();
724 /// let a: i32 = lua.get("a").unwrap();
725 /// assert_eq!(a, 5);
726 /// ```
727 #[inline]
728 pub fn get<'l, V, I>(&'l mut self, index: I) -> Option<V>
729 where I: Borrow<str>,
730 V: LuaRead<PushGuard<&'l mut Lua<'lua>>>
731 {
732 let index = CString::new(index.borrow()).unwrap();
733 unsafe {
734 ffi::lua_getglobal(self.lua.0, index.as_ptr());
735 }
736 if unsafe { ffi::lua_isnil(self.as_lua().0, -1) } {
737 let raw_lua = self.as_lua();
738 let _guard = PushGuard {
739 lua: self,
740 size: 1,
741 raw_lua: raw_lua,
742 };
743 return None;
744 }
745 let raw_lua = self.as_lua();
746 let guard = PushGuard {
747 lua: self,
748 size: 1,
749 raw_lua: raw_lua,
750 };
751 LuaRead::lua_read(guard).ok()
752 }
753
754 /// Reads the value of a global, capturing the context by value.
755 #[inline]
756 pub fn into_get<V, I>(self, index: I) -> Result<V, PushGuard<Self>>
757 where I: Borrow<str>,
758 V: LuaRead<PushGuard<Lua<'lua>>>
759 {
760 let index = CString::new(index.borrow()).unwrap();
761 unsafe {
762 ffi::lua_getglobal(self.lua.0, index.as_ptr());
763 }
764 let is_nil = unsafe { ffi::lua_isnil(self.as_lua().0, -1) };
765 let raw_lua = self.as_lua();
766 let guard = PushGuard {
767 lua: self,
768 size: 1,
769 raw_lua: raw_lua,
770 };
771 if is_nil {
772 Err(guard)
773 } else {
774 LuaRead::lua_read(guard)
775 }
776 }
777
778 /// Modifies the value of a global variable.
779 ///
780 /// If you want to write an array, you are encouraged to use
781 /// [the `empty_array` method](#method.empty_array) instead.
782 ///
783 /// The type must implement the `PushOne` trait. See
784 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
785 /// information.
786 ///
787 /// # Example
788 ///
789 /// ```
790 /// use hlua::Lua;
791 /// let mut lua = Lua::new();
792 ///
793 /// lua.set("a", 12);
794 /// let six: i32 = lua.execute("return a / 2;").unwrap();
795 /// assert_eq!(six, 6);
796 /// ```
797 #[inline]
798 pub fn set<I, V, E>(&mut self, index: I, value: V)
799 where I: Borrow<str>,
800 for<'a> V: PushOne<&'a mut Lua<'lua>, Err = E>,
801 E: Into<Void>,
802 {
803 match self.checked_set(index, value) {
804 Ok(_) => (),
805 Err(_) => unreachable!(),
806 }
807 }
808
809 /// Modifies the value of a global variable.
810 // TODO: docs
811 #[inline]
812 pub fn checked_set<I, V, E>(&mut self, index: I, value: V) -> Result<(), E>
813 where I: Borrow<str>,
814 for<'a> V: PushOne<&'a mut Lua<'lua>, Err = E>
815 {
816 unsafe {
817 // TODO: can be simplified
818 let mut me = self;
819 ffi::lua_pushglobaltable(me.lua.0);
820 match index.borrow().push_to_lua(&mut me) {
821 Ok(pushed) => {
822 debug_assert_eq!(pushed.size, 1);
823 pushed.forget()
824 }
825 Err(_) => unreachable!(),
826 };
827 match value.push_to_lua(&mut me) {
828 Ok(pushed) => {
829 assert_eq!(pushed.size, 1);
830 pushed.forget()
831 }
832 Err((err, lua)) => {
833 ffi::lua_pop(lua.lua.0, 2);
834 return Err(err);
835 }
836 };
837 ffi::lua_settable(me.lua.0, -3);
838 ffi::lua_pop(me.lua.0, 1);
839 Ok(())
840 }
841 }
842
843 /// Sets the value of a global variable to an empty array, then loads it.
844 ///
845 /// This is the function you should use if you want to set the value of a global variable to
846 /// an array. After calling it, you will obtain a `LuaTable` object which you can then fill
847 /// with the elements of the array.
848 ///
849 /// # Example
850 ///
851 /// ```
852 /// use hlua::Lua;
853 /// let mut lua = Lua::new();
854 /// lua.openlibs(); // Necessary for `ipairs`.
855 ///
856 /// {
857 /// let mut array = lua.empty_array("my_values");
858 /// array.set(1, 10); // Don't forget that Lua arrays are indexed from 1.
859 /// array.set(2, 15);
860 /// array.set(3, 20);
861 /// }
862 ///
863 /// let sum: i32 = lua.execute(r#"
864 /// local sum = 0
865 /// for i, val in ipairs(my_values) do
866 /// sum = sum + val
867 /// end
868 /// return sum
869 /// "#).unwrap();
870 ///
871 /// assert_eq!(sum, 45);
872 /// ```
873 #[inline]
874 pub fn empty_array<'a, I>(&'a mut self, index: I) -> LuaTable<PushGuard<&'a mut Lua<'lua>>>
875 where I: Borrow<str>
876 {
877 unsafe {
878 let mut me = self;
879 ffi::lua_pushglobaltable(me.lua.0);
880 match index.borrow().push_to_lua(&mut me) {
881 Ok(pushed) => pushed.forget(),
882 Err(_) => unreachable!(),
883 };
884 ffi::lua_newtable(me.lua.0);
885 ffi::lua_settable(me.lua.0, -3);
886 ffi::lua_pop(me.lua.0, 1);
887
888 // TODO: cleaner implementation
889 me.get(index).unwrap()
890 }
891 }
892
893 /// Loads the array containing the global variables.
894 ///
895 /// In lua, the global variables accessible from the lua code are all part of a table which
896 /// you can load here.
897 ///
898 /// # Examples
899 ///
900 /// The function can be used to write global variables, just like `set`.
901 ///
902 /// ```
903 /// use hlua::Lua;
904 /// let mut lua = Lua::new();
905 /// lua.globals_table().set("a", 5);
906 /// assert_eq!(lua.get::<i32, _>("a"), Some(5));
907 /// ```
908 ///
909 /// A more useful feature for this function is that it allows you to set the metatable of the
910 /// global variables. See TODO for more info.
911 ///
912 /// ```
913 /// use hlua::Lua;
914 /// use hlua::AnyLuaValue;
915 ///
916 /// let mut lua = Lua::new();
917 /// {
918 /// let mut metatable = lua.globals_table().get_or_create_metatable();
919 /// metatable.set("__index", hlua::function2(|_: AnyLuaValue, var: String| -> AnyLuaValue {
920 /// println!("The user tried to access the variable {:?}", var);
921 /// AnyLuaValue::LuaNumber(48.0)
922 /// }));
923 /// }
924 ///
925 /// let b: i32 = lua.execute("return b * 2;").unwrap();
926 /// // -> The user tried to access the variable "b"
927 ///
928 /// assert_eq!(b, 96);
929 /// ```
930 #[inline]
931 pub fn globals_table<'a>(&'a mut self) -> LuaTable<PushGuard<&'a mut Lua<'lua>>> {
932 unsafe {
933 ffi::lua_pushglobaltable(self.lua.0);
934 }
935 let raw_lua = self.as_lua();
936 let guard = PushGuard {
937 lua: self,
938 size: 1,
939 raw_lua: raw_lua,
940 };
941 LuaRead::lua_read(guard).ok().unwrap()
942 }
943}
944
945impl<'lua> Drop for Lua<'lua> {
946 #[inline]
947 fn drop(&mut self) {
948 if self.must_be_closed {
949 unsafe { ffi::lua_close(self.lua.0) }
950 }
951 }
952}
953
954impl<L> Drop for PushGuard<L> {
955 #[inline]
956 fn drop(&mut self) {
957 if self.size != 0 {
958 unsafe {
959 ffi::lua_pop(self.raw_lua.0, self.size);
960 }
961 }
962 }
963}
964
965#[cfg(test)]
966mod tests {
967 use Lua;
968 use LuaError;
969
970 #[test]
971 fn open_base_opens_base_library() {
972 let mut lua = Lua::new();
973 match lua.execute::<()>("return assert(true)") {
974 Err(LuaError::ExecutionError(_)) => { },
975 Err(_) => panic!("Wrong error"),
976 Ok(_) => panic!("Unexpected success"),
977 }
978 lua.open_base();
979 let result: bool = lua.execute("return assert(true)").unwrap();
980 assert_eq!(result, true);
981 }
982
983 #[test]
984 fn opening_all_libraries_doesnt_panic() {
985 let mut lua = Lua::new();
986 lua.open_base();
987 lua.open_bit32();
988 lua.open_coroutine();
989 lua.open_debug();
990 lua.open_io();
991 lua.open_math();
992 lua.open_os();
993 lua.open_package();
994 lua.open_string();
995 lua.open_table();
996 }
997}