hlua/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 unsafe {
227 use std::{mem, ptr};
228
229 let mut res;
230 res = mem::MaybeUninit::uninit();
231 ptr::copy_nonoverlapping(&self.lua, res.as_mut_ptr(), 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.assume_init()
239 }
240 }
241}
242
243/// Trait for objects that have access to a Lua context. When using a context returned by a
244/// `AsLua`, you are not allowed to modify the stack.
245// TODO: the lifetime should be an associated lifetime instead
246pub unsafe trait AsLua<'lua> {
247 fn as_lua(&self) -> LuaContext;
248}
249
250/// Trait for objects that have access to a Lua context. You are allowed to modify the stack, but
251/// it must be in the same state as it was when you started.
252// TODO: the lifetime should be an associated lifetime instead
253pub unsafe trait AsMutLua<'lua>: AsLua<'lua> {
254 /// Returns the raw Lua context.
255 fn as_mut_lua(&mut self) -> LuaContext;
256}
257
258/// Opaque type that contains the raw Lua context.
259// TODO: probably no longer necessary
260#[derive(Copy, Clone, Debug)]
261pub struct LuaContext(*mut ffi::lua_State);
262
263impl LuaContext {
264 /// Return a pointer to the inner `lua_State` for this context. This is an escape hatch that
265 /// lets the caller perform arbitrary operations against the FFI directly.
266 ///
267 /// Be careful: performing operations on this state might invalidate assumptions made in
268 /// higher-level APIs. For example, pushing a value onto the Lua stack will cause `PushGuard`s
269 /// in Rust code to be out of sync with the Lua stack.
270 #[doc(hidden)]
271 #[inline]
272 pub fn state_ptr(&self) -> *mut ffi::lua_State {
273 self.0
274 }
275}
276
277unsafe impl Send for LuaContext {}
278
279unsafe impl<'a, 'lua> AsLua<'lua> for Lua<'lua> {
280 #[inline]
281 fn as_lua(&self) -> LuaContext {
282 self.lua
283 }
284}
285
286unsafe impl<'lua> AsMutLua<'lua> for Lua<'lua> {
287 #[inline]
288 fn as_mut_lua(&mut self) -> LuaContext {
289 self.lua
290 }
291}
292
293unsafe impl<'lua, L> AsLua<'lua> for PushGuard<L>
294 where L: AsMutLua<'lua>
295{
296 #[inline]
297 fn as_lua(&self) -> LuaContext {
298 self.lua.as_lua()
299 }
300}
301
302unsafe impl<'lua, L> AsMutLua<'lua> for PushGuard<L>
303 where L: AsMutLua<'lua>
304{
305 #[inline]
306 fn as_mut_lua(&mut self) -> LuaContext {
307 self.lua.as_mut_lua()
308 }
309}
310
311unsafe impl<'a, 'lua, L: ?Sized> AsLua<'lua> for &'a L
312 where L: AsLua<'lua>
313{
314 #[inline]
315 fn as_lua(&self) -> LuaContext {
316 (**self).as_lua()
317 }
318}
319
320unsafe impl<'a, 'lua, L: ?Sized> AsLua<'lua> for &'a mut L
321 where L: AsLua<'lua>
322{
323 #[inline]
324 fn as_lua(&self) -> LuaContext {
325 (**self).as_lua()
326 }
327}
328
329unsafe impl<'a, 'lua, L: ?Sized> AsMutLua<'lua> for &'a mut L
330 where L: AsMutLua<'lua>
331{
332 #[inline]
333 fn as_mut_lua(&mut self) -> LuaContext {
334 (**self).as_mut_lua()
335 }
336}
337
338/// Types that can be given to a Lua context, for example with `lua.set()` or as a return value
339/// of a function.
340pub trait Push<L> {
341 /// Error that can happen when pushing a value.
342 type Err;
343
344 /// Pushes the value on the top of the stack.
345 ///
346 /// Must return a guard representing the elements that have been pushed.
347 ///
348 /// You can implement this for any type you want by redirecting to call to
349 /// another implementation (for example `5.push_to_lua`) or by calling
350 /// `userdata::push_userdata`.
351 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (Self::Err, L)>;
352
353 /// Same as `push_to_lua` but can only succeed and is only available if `Err` is `Void`.
354 // TODO: when https://github.com/rust-lang/rust/issues/20041 is fixed, use `Self::Err == Void`
355 #[inline]
356 fn push_no_err<E>(self, lua: L) -> PushGuard<L>
357 where Self: Sized,
358 Self: Push<L, Err = E>,
359 E: Into<Void>,
360 {
361 match self.push_to_lua(lua) {
362 Ok(p) => p,
363 Err(_) => unreachable!(),
364 }
365 }
366}
367
368/// Extension trait for `Push`. Guarantees that only one element will be pushed.
369///
370/// This should be implemented on most types that implement `Push`, except for tuples.
371///
372/// > **Note**: Implementing this trait on a type that pushes multiple elements will most likely
373/// > result in panics.
374// Note for the implementation: since this trait is not unsafe, it is mostly a hint. Functions can
375// require this trait if they only accept one pushed element, but they must also add a runtime
376// assertion to make sure that only one element was actually pushed.
377pub trait PushOne<L>: Push<L> {}
378
379/// Type that cannot be instantiated.
380///
381/// Will be replaced with `!` eventually (https://github.com/rust-lang/rust/issues/35121).
382#[derive(Debug, Copy, Clone)]
383pub enum Void {}
384
385impl fmt::Display for Void {
386 fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
387 unreachable!("Void cannot be instantiated")
388 }
389}
390
391/// Types that can be obtained from a Lua context.
392///
393/// Most types that implement `Push` also implement `LuaRead`, but this is not always the case
394/// (for example `&'static str` implements `Push` but not `LuaRead`).
395pub trait LuaRead<L>: Sized {
396 /// Reads the data from Lua.
397 #[inline]
398 fn lua_read(lua: L) -> Result<Self, L> {
399 LuaRead::lua_read_at_position(lua, -1)
400 }
401
402 /// Reads the data from Lua at a given position.
403 fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L>;
404}
405
406/// Error that can happen when executing Lua code.
407#[derive(Debug)]
408pub enum LuaError {
409 /// There was a syntax error when parsing the Lua code.
410 SyntaxError(String),
411
412 /// There was an error during execution of the Lua code
413 /// (for example not enough parameters for a function call).
414 ExecutionError(String),
415
416 /// There was an IoError while reading the source code to execute.
417 ReadError(IoError),
418
419 /// The call to `execute` has requested the wrong type of data.
420 WrongType,
421}
422
423impl fmt::Display for LuaError {
424 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
425 use LuaError::*;
426
427 match *self {
428 SyntaxError(ref s) => write!(f, "Syntax error: {}", s),
429 ExecutionError(ref s) => write!(f, "Execution error: {}", s),
430 ReadError(ref e) => write!(f, "Read error: {}", e),
431 WrongType => write!(f, "Wrong type returned by Lua"),
432 }
433 }
434}
435
436impl Error for LuaError {
437 fn description(&self) -> &str {
438 use LuaError::*;
439
440 match *self {
441 SyntaxError(ref s) => &s,
442 ExecutionError(ref s) => &s,
443 ReadError(_) => "read error",
444 WrongType => "wrong type returned by Lua",
445 }
446 }
447
448 fn cause(&self) -> Option<&Error> {
449 use LuaError::*;
450
451 match *self {
452 SyntaxError(_) => None,
453 ExecutionError(_) => None,
454 ReadError(ref e) => Some(e),
455 WrongType => None,
456 }
457 }
458}
459
460impl From<io::Error> for LuaError {
461 fn from(e: io::Error) -> Self {
462 LuaError::ReadError(e)
463 }
464}
465
466impl<'lua> Lua<'lua> {
467 /// Builds a new empty Lua context.
468 ///
469 /// There are no global variables and the registry is totally empty. Even the functions from
470 /// the standard library can't be used.
471 ///
472 /// If you want to use the Lua standard library in the scripts of this context, see
473 /// [the openlibs method](#method.openlibs)
474 ///
475 /// # Example
476 ///
477 /// ```
478 /// use hlua::Lua;
479 /// let mut lua = Lua::new();
480 /// ```
481 ///
482 /// # Panic
483 ///
484 /// The function panics if the underlying call to `lua_newstate` fails
485 /// (which indicates lack of memory).
486 #[inline]
487 pub fn new() -> Lua<'lua> {
488 let lua = unsafe { ffi::lua_newstate(alloc, std::ptr::null_mut()) };
489 if lua.is_null() {
490 panic!("lua_newstate failed");
491 }
492
493 // this alloc function is required to create a lua state.
494 extern "C" fn alloc(_ud: *mut libc::c_void,
495 ptr: *mut libc::c_void,
496 _osize: libc::size_t,
497 nsize: libc::size_t)
498 -> *mut libc::c_void {
499 unsafe {
500 if nsize == 0 {
501 libc::free(ptr as *mut libc::c_void);
502 std::ptr::null_mut()
503 } else {
504 libc::realloc(ptr, nsize)
505 }
506 }
507 }
508
509 // called whenever lua encounters an unexpected error.
510 extern "C" fn panic(lua: *mut ffi::lua_State) -> libc::c_int {
511 let err = unsafe { ffi::lua_tostring(lua, -1) };
512 let err = unsafe { CStr::from_ptr(err) };
513 let err = String::from_utf8(err.to_bytes().to_vec()).unwrap();
514 panic!("PANIC: unprotected error in call to Lua API ({})\n", err);
515 }
516
517 unsafe { ffi::lua_atpanic(lua, panic) };
518
519 Lua {
520 lua: LuaContext(lua),
521 must_be_closed: true,
522 marker: PhantomData,
523 }
524 }
525
526 /// Takes an existing `lua_State` and build a Lua object from it.
527 ///
528 /// If `close_at_the_end` is true, `lua_close` will be called on the `lua_State` in the
529 /// destructor.
530 #[inline]
531 pub unsafe fn from_existing_state<T>(lua: *mut T, close_at_the_end: bool) -> Lua<'lua> {
532 Lua {
533 lua: std::mem::transmute(lua),
534 must_be_closed: close_at_the_end,
535 marker: PhantomData,
536 }
537 }
538
539 /// Opens all standard Lua libraries.
540 ///
541 /// See the reference for the standard library here:
542 /// https://www.lua.org/manual/5.2/manual.html#6
543 ///
544 /// This is done by calling `luaL_openlibs`.
545 ///
546 /// # Example
547 ///
548 /// ```
549 /// use hlua::Lua;
550 /// let mut lua = Lua::new();
551 /// lua.openlibs();
552 /// ```
553 #[inline]
554 pub fn openlibs(&mut self) {
555 unsafe { ffi::luaL_openlibs(self.lua.0) }
556 }
557
558 /// Opens base library.
559 ///
560 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_base
561 #[inline]
562 pub fn open_base(&mut self) {
563 unsafe { ffi::luaopen_base(self.lua.0) }
564 }
565
566 /// Opens bit32 library.
567 ///
568 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_bit32
569 #[inline]
570 pub fn open_bit32(&mut self) {
571 unsafe { ffi::luaopen_bit32(self.lua.0) }
572 }
573
574 /// Opens coroutine library.
575 ///
576 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_coroutine
577 #[inline]
578 pub fn open_coroutine(&mut self) {
579 unsafe { ffi::luaopen_coroutine(self.lua.0) }
580 }
581
582 /// Opens debug library.
583 ///
584 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_debug
585 #[inline]
586 pub fn open_debug(&mut self) {
587 unsafe { ffi::luaopen_debug(self.lua.0) }
588 }
589
590 /// Opens io library.
591 ///
592 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_io
593 #[inline]
594 pub fn open_io(&mut self) {
595 unsafe { ffi::luaopen_io(self.lua.0) }
596 }
597
598 /// Opens math library.
599 ///
600 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_math
601 #[inline]
602 pub fn open_math(&mut self) {
603 unsafe { ffi::luaopen_math(self.lua.0) }
604 }
605
606 /// Opens os library.
607 ///
608 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_os
609 #[inline]
610 pub fn open_os(&mut self) {
611 unsafe { ffi::luaopen_os(self.lua.0) }
612 }
613
614 /// Opens package library.
615 ///
616 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_package
617 #[inline]
618 pub fn open_package(&mut self) {
619 unsafe { ffi::luaopen_package(self.lua.0) }
620 }
621
622 /// Opens string library.
623 ///
624 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_string
625 #[inline]
626 pub fn open_string(&mut self) {
627 unsafe { ffi::luaopen_string(self.lua.0) }
628 }
629
630 /// Opens table library.
631 ///
632 /// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_table
633 #[inline]
634 pub fn open_table(&mut self) {
635 unsafe { ffi::luaopen_table(self.lua.0) }
636 }
637
638 /// Executes some Lua code in the context.
639 ///
640 /// The code will have access to all the global variables you set with methods such as `set`.
641 /// Every time you execute some code in the context, the code can modify these global variables.
642 ///
643 /// The template parameter of this function is the return type of the expression that is being
644 /// evaluated.
645 /// In order to avoid compilation error, you should call this function either by doing
646 /// `lua.execute::<T>(...)` or `let result: T = lua.execute(...);` where `T` is the type of
647 /// the expression.
648 /// The function will return an error if the actual return type of the expression doesn't
649 /// match the template parameter.
650 ///
651 /// The return type must implement the `LuaRead` trait. See
652 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
653 /// information.
654 ///
655 /// # Examples
656 ///
657 /// Without a return value:
658 ///
659 /// ```
660 /// use hlua::Lua;
661 /// let mut lua = Lua::new();
662 /// lua.execute::<()>("function multiply_by_two(a) return a * 2 end").unwrap();
663 /// lua.execute::<()>("twelve = multiply_by_two(6)").unwrap();
664 /// ```
665 ///
666 /// With a return value:
667 ///
668 /// ```
669 /// use hlua::Lua;
670 /// let mut lua = Lua::new();
671 ///
672 /// let twelve: i32 = lua.execute("return 3 * 4;").unwrap();
673 /// let sixty = lua.execute::<i32>("return 6 * 10;").unwrap();
674 /// ```
675 #[inline]
676 pub fn execute<'a, T>(&'a mut self, code: &str) -> Result<T, LuaError>
677 where T: for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>
678 {
679 let mut f = try!(lua_functions::LuaFunction::load(self, code));
680 f.call()
681 }
682
683 /// Executes some Lua code on the context.
684 ///
685 /// This does the same thing as [the `execute` method](#method.execute), but the code to
686 /// execute is loaded from an object that implements `Read`.
687 ///
688 /// Use this method when you potentially have a large amount of code (for example if you read
689 /// the code from a file) in order to avoid having to put everything in memory first before
690 /// passing it to the Lua interpreter.
691 ///
692 /// # Example
693 ///
694 /// ```no_run
695 /// use std::fs::File;
696 /// use hlua::Lua;
697 ///
698 /// let mut lua = Lua::new();
699 /// let script = File::open("script.lua").unwrap();
700 /// lua.execute_from_reader::<(), _>(script).unwrap();
701 /// ```
702 #[inline]
703 pub fn execute_from_reader<'a, T, R>(&'a mut self, code: R) -> Result<T, LuaError>
704 where T: for<'g> LuaRead<PushGuard<&'g mut PushGuard<&'a mut Lua<'lua>>>>,
705 R: Read
706 {
707 let mut f = try!(lua_functions::LuaFunction::load_from_reader(self, code));
708 f.call()
709 }
710
711 /// Reads the value of a global variable.
712 ///
713 /// Returns `None` if the variable doesn't exist or has the wrong type.
714 ///
715 /// The type must implement the `LuaRead` trait. See
716 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
717 /// information.
718 ///
719 /// # Example
720 ///
721 /// ```
722 /// use hlua::Lua;
723 /// let mut lua = Lua::new();
724 /// lua.execute::<()>("a = 5").unwrap();
725 /// let a: i32 = lua.get("a").unwrap();
726 /// assert_eq!(a, 5);
727 /// ```
728 #[inline]
729 pub fn get<'l, V, I>(&'l mut self, index: I) -> Option<V>
730 where I: Borrow<str>,
731 V: LuaRead<PushGuard<&'l mut Lua<'lua>>>
732 {
733 let index = CString::new(index.borrow()).unwrap();
734 unsafe {
735 ffi::lua_getglobal(self.lua.0, index.as_ptr());
736 }
737 if unsafe { ffi::lua_isnil(self.as_lua().0, -1) } {
738 let raw_lua = self.as_lua();
739 let _guard = PushGuard {
740 lua: self,
741 size: 1,
742 raw_lua: raw_lua,
743 };
744 return None;
745 }
746 let raw_lua = self.as_lua();
747 let guard = PushGuard {
748 lua: self,
749 size: 1,
750 raw_lua: raw_lua,
751 };
752 LuaRead::lua_read(guard).ok()
753 }
754
755 /// Reads the value of a global, capturing the context by value.
756 #[inline]
757 pub fn into_get<V, I>(self, index: I) -> Result<V, PushGuard<Self>>
758 where I: Borrow<str>,
759 V: LuaRead<PushGuard<Lua<'lua>>>
760 {
761 let index = CString::new(index.borrow()).unwrap();
762 unsafe {
763 ffi::lua_getglobal(self.lua.0, index.as_ptr());
764 }
765 let is_nil = unsafe { ffi::lua_isnil(self.as_lua().0, -1) };
766 let raw_lua = self.as_lua();
767 let guard = PushGuard {
768 lua: self,
769 size: 1,
770 raw_lua: raw_lua,
771 };
772 if is_nil {
773 Err(guard)
774 } else {
775 LuaRead::lua_read(guard)
776 }
777 }
778
779 /// Modifies the value of a global variable.
780 ///
781 /// If you want to write an array, you are encouraged to use
782 /// [the `empty_array` method](#method.empty_array) instead.
783 ///
784 /// The type must implement the `PushOne` trait. See
785 /// [the documentation at the crate root](index.html#pushing-and-loading-values) for more
786 /// information.
787 ///
788 /// # Example
789 ///
790 /// ```
791 /// use hlua::Lua;
792 /// let mut lua = Lua::new();
793 ///
794 /// lua.set("a", 12);
795 /// let six: i32 = lua.execute("return a / 2;").unwrap();
796 /// assert_eq!(six, 6);
797 /// ```
798 #[inline]
799 pub fn set<I, V, E>(&mut self, index: I, value: V)
800 where I: Borrow<str>,
801 for<'a> V: PushOne<&'a mut Lua<'lua>, Err = E>,
802 E: Into<Void>,
803 {
804 match self.checked_set(index, value) {
805 Ok(_) => (),
806 Err(_) => unreachable!(),
807 }
808 }
809
810 /// Modifies the value of a global variable.
811 // TODO: docs
812 #[inline]
813 pub fn checked_set<I, V, E>(&mut self, index: I, value: V) -> Result<(), E>
814 where I: Borrow<str>,
815 for<'a> V: PushOne<&'a mut Lua<'lua>, Err = E>
816 {
817 unsafe {
818 // TODO: can be simplified
819 let mut me = self;
820 ffi::lua_pushglobaltable(me.lua.0);
821 match index.borrow().push_to_lua(&mut me) {
822 Ok(pushed) => {
823 debug_assert_eq!(pushed.size, 1);
824 pushed.forget()
825 }
826 Err(_) => unreachable!(),
827 };
828 match value.push_to_lua(&mut me) {
829 Ok(pushed) => {
830 assert_eq!(pushed.size, 1);
831 pushed.forget()
832 }
833 Err((err, lua)) => {
834 ffi::lua_pop(lua.lua.0, 2);
835 return Err(err);
836 }
837 };
838 ffi::lua_settable(me.lua.0, -3);
839 ffi::lua_pop(me.lua.0, 1);
840 Ok(())
841 }
842 }
843
844 /// Sets the value of a global variable to an empty array, then loads it.
845 ///
846 /// This is the function you should use if you want to set the value of a global variable to
847 /// an array. After calling it, you will obtain a `LuaTable` object which you can then fill
848 /// with the elements of the array.
849 ///
850 /// # Example
851 ///
852 /// ```
853 /// use hlua::Lua;
854 /// let mut lua = Lua::new();
855 /// lua.openlibs(); // Necessary for `ipairs`.
856 ///
857 /// {
858 /// let mut array = lua.empty_array("my_values");
859 /// array.set(1, 10); // Don't forget that Lua arrays are indexed from 1.
860 /// array.set(2, 15);
861 /// array.set(3, 20);
862 /// }
863 ///
864 /// let sum: i32 = lua.execute(r#"
865 /// local sum = 0
866 /// for i, val in ipairs(my_values) do
867 /// sum = sum + val
868 /// end
869 /// return sum
870 /// "#).unwrap();
871 ///
872 /// assert_eq!(sum, 45);
873 /// ```
874 #[inline]
875 pub fn empty_array<'a, I>(&'a mut self, index: I) -> LuaTable<PushGuard<&'a mut Lua<'lua>>>
876 where I: Borrow<str>
877 {
878 unsafe {
879 let mut me = self;
880 ffi::lua_pushglobaltable(me.lua.0);
881 match index.borrow().push_to_lua(&mut me) {
882 Ok(pushed) => pushed.forget(),
883 Err(_) => unreachable!(),
884 };
885 ffi::lua_newtable(me.lua.0);
886 ffi::lua_settable(me.lua.0, -3);
887 ffi::lua_pop(me.lua.0, 1);
888
889 // TODO: cleaner implementation
890 me.get(index).unwrap()
891 }
892 }
893
894 /// Loads the array containing the global variables.
895 ///
896 /// In lua, the global variables accessible from the lua code are all part of a table which
897 /// you can load here.
898 ///
899 /// # Examples
900 ///
901 /// The function can be used to write global variables, just like `set`.
902 ///
903 /// ```
904 /// use hlua::Lua;
905 /// let mut lua = Lua::new();
906 /// lua.globals_table().set("a", 5);
907 /// assert_eq!(lua.get::<i32, _>("a"), Some(5));
908 /// ```
909 ///
910 /// A more useful feature for this function is that it allows you to set the metatable of the
911 /// global variables. See TODO for more info.
912 ///
913 /// ```
914 /// use hlua::Lua;
915 /// use hlua::AnyLuaValue;
916 ///
917 /// let mut lua = Lua::new();
918 /// {
919 /// let mut metatable = lua.globals_table().get_or_create_metatable();
920 /// metatable.set("__index", hlua::function2(|_: AnyLuaValue, var: String| -> AnyLuaValue {
921 /// println!("The user tried to access the variable {:?}", var);
922 /// AnyLuaValue::LuaNumber(48.0)
923 /// }));
924 /// }
925 ///
926 /// let b: i32 = lua.execute("return b * 2;").unwrap();
927 /// // -> The user tried to access the variable "b"
928 ///
929 /// assert_eq!(b, 96);
930 /// ```
931 #[inline]
932 pub fn globals_table<'a>(&'a mut self) -> LuaTable<PushGuard<&'a mut Lua<'lua>>> {
933 unsafe {
934 ffi::lua_pushglobaltable(self.lua.0);
935 }
936 let raw_lua = self.as_lua();
937 let guard = PushGuard {
938 lua: self,
939 size: 1,
940 raw_lua: raw_lua,
941 };
942 LuaRead::lua_read(guard).ok().unwrap()
943 }
944}
945
946impl<'lua> Drop for Lua<'lua> {
947 #[inline]
948 fn drop(&mut self) {
949 if self.must_be_closed {
950 unsafe { ffi::lua_close(self.lua.0) }
951 }
952 }
953}
954
955impl<L> Drop for PushGuard<L> {
956 #[inline]
957 fn drop(&mut self) {
958 if self.size != 0 {
959 unsafe {
960 ffi::lua_pop(self.raw_lua.0, self.size);
961 }
962 }
963 }
964}
965
966#[cfg(test)]
967mod tests {
968 use Lua;
969 use LuaError;
970
971 #[test]
972 fn open_base_opens_base_library() {
973 let mut lua = Lua::new();
974 match lua.execute::<()>("return assert(true)") {
975 Err(LuaError::ExecutionError(_)) => { },
976 Err(_) => panic!("Wrong error"),
977 Ok(_) => panic!("Unexpected success"),
978 }
979 lua.open_base();
980 let result: bool = lua.execute("return assert(true)").unwrap();
981 assert_eq!(result, true);
982 }
983
984 #[test]
985 fn opening_all_libraries_doesnt_panic() {
986 let mut lua = Lua::new();
987 lua.open_base();
988 lua.open_bit32();
989 lua.open_coroutine();
990 lua.open_debug();
991 lua.open_io();
992 lua.open_math();
993 lua.open_os();
994 lua.open_package();
995 lua.open_string();
996 lua.open_table();
997 }
998}