1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Using the Lua programming language with the [`sandkiste`] sandboxing API
//!
//! # Features
//!
//! This crate allows executing [Lua](https://www.lua.org/) code in a sandbox
//! where memory usage and the number of executed Lua instructions can be
//! limited.
//!
//! It uses the [`sandkiste`] API, which is an interface that can also be used
//! for sandboxing other scripting languages than Lua.
//!
//! It is possible to call Lua functions from Rust or to call Rust closures
//! from Lua. However, execution time in Rust (or waiting for I/O) is not
//! counting towards resource limits.
//!
//! # Different Lua versions
//!
//! Upon building, either Lua version 5.3 or 5.4 must be selected by specifying
//! one of the features `Lua5_3` or `Lua5_4`. Currently, it is not possible to
//! build this crate with support for both Lua versions at the same time.
//!
//! To allow lifting this restriction in future, items are contained in a
//! module reflecting the Lua version being used (module `v5_3` or `v5_4`).
//!
//! # Example use
//!
//! ```
//! use sandkiste::prelude::*;
//! #[cfg(feature = "Lua5_3")]
//! use sandkiste_lua::v5_3::{LuaMachine, LuaDatum};
//! #[cfg(feature = "Lua5_4")]
//! use sandkiste_lua::v5_4::{LuaMachine, LuaDatum};
//! use std::cell::RefCell;
//!
//! let output_cell = RefCell::new(String::new());
//!
//! let machine = LuaMachine::new();
//!
//! machine.load_stdlib().expect("could not load Lua standard lib");
//! machine
//!     .compile(
//!         Some("init".to_string()),
//!         "-- require 'some_library'",
//!     )
//!     .expect("could not compile initialization code")
//!     .call([])
//!     .expect("could not run initialization code");
//!
//! // remove certain functions from Lua's standard library:
//! machine.seal().expect("could not seal sandbox");
//!
//! let my_print = machine
//!     .callback_1arg(|s| {
//!         let s = s.try_as_str()?;
//!         let mut output = output_cell.borrow_mut();
//!         output.push_str(s);
//!         Ok([])
//!     })
//!     .expect("could not create closure for myprint");
//! machine
//!     .compile(
//!         Some("set_myprint".to_string()),
//!         "myprint = ...",
//!     )
//!     .expect("could not compile code to set myprint")
//!     .call([my_print])
//!     .expect("could not run code to set myprint");
//!
//! let main = machine
//!     .compile(
//!         Some("main".to_string()),
//!         "\
//!             local args = {...}\n\
//!             myprint('Hello ')\n\
//!             myprint(args[1])\n\
//!             myprint('!')\n\
//!         "
//!     )
//!     .expect("could not compile main Lua function");
//!
//! let name: LuaDatum = "Rust".into();
//! main.call([name]).expect("runtime error in main Lua function");
//!
//! // dropping these lets us move out of `output_cell`, which is still
//! // borrowed by the closure that has been moved to the machine:
//! drop(main);
//! drop(machine);
//!
//! let output = output_cell.into_inner();
//! assert_eq!(output, "Hello Rust!");
//! ```

#![warn(missing_docs)]

pub mod cmach;

#[cfg(feature = "Lua5_3")]
pub mod v5_3 {
    //! Support for Lua 5.3
    //!
    //! This module provides data structures implementing the
    //! [`sandkiste`] API to provide support for version 5.3 of the
    //! [Lua programming language](https://www.lua.org/).
    //! For an overview on how to use these data structures, refer
    //! to the [top-level module documentation](super).

    include!("common.rs");
}

#[cfg(feature = "Lua5_4")]
pub mod v5_4 {
    //! Support for Lua 5.4
    //!
    //! This module provides data structures implementing the
    //! [`sandkiste`] API to provide support for version 5.4 of the
    //! [Lua programming language](https://www.lua.org/).
    //! For an overview on how to use these data structures, refer
    //! to the [top-level module documentation](super).

    include!("common.rs");
}

#[cfg(any())] // never expose, only for rustfmt
pub mod common;

#[cfg(test)]
mod tests;