redis_lua/
lib.rs

1//!
2//! redis-lua is a Lua scripting helper for [`redis-rs`](https://github.com/mitsuhiko/redis-rs)
3//!
4//! redis-lua allows to insert Redis Lua scripts in Rust code in safer manner. The key features of redis-lua are:
5//!
6//! * Compile-time lint for Redis Lua scripts.
7//! * Capturing Rust variables in Lua scripts.
8//! * Safe argument substitution.
9//! * Safely joining multiple Lua scripts.
10//!
11//! # Invoke a Lua script
12//!
13//! [`lua`][] macro allows to create the Lua script. The script object implements [`Script`][] trait.
14//! The return value from the script can be converted to any types which implement [`redis::FromRedisValue`][].
15//!
16//! ```rust
17//! use redis_lua::lua;
18//!
19//! # fn main() {
20//! let mut cli = redis::Client::open("redis://localhost").unwrap();
21//!
22//! let script = lua!(return 1 + 2);
23//! let num: usize = script.invoke(&mut cli).unwrap();
24//! assert_eq!(num, 3);
25//! # }
26//! ```
27//!
28//! Any Lua syntax supported by Redis Lua is usable.
29//!
30//! * if-else
31//!
32//! ```rust
33//! # use redis_lua::lua;
34//! #
35//! # fn main() {
36//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
37//! #
38//! # let script =
39//! lua!(
40//!   if 3 > 1 then
41//!     return 3
42//!   else
43//!     return 1
44//!   end
45//! );
46//! # let num: usize = script.invoke(&mut cli).unwrap();
47//! # assert_eq!(num, 3);
48//! # }
49//! ```
50//!
51//! * for-loop
52//!
53//! ```rust
54//! # use redis_lua::lua;
55//! #
56//! # fn main() {
57//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
58//! #
59//! # let script =
60//! lua!(
61//!   local sum = 0
62//!   for i=1,10 do
63//!      sum = sum + i
64//!   end
65//!   return sum
66//! );
67//! # let num: usize = script.invoke(&mut cli).unwrap();
68//! # assert_eq!(num, 55);
69//! # }
70//! ```
71//!
72//! # Error reporting
73//!
74//! Errors in Lua scripts (such as undefined variables) are detected at compile time.
75//!
76//! ```rust,ignore
77//! # use redis_lua::lua;
78//! #
79//! # fn main() {
80//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
81//! #
82//! # let script =
83//! lua!(
84//!   return a + 1
85//! );
86//! # let num: usize = script.invoke(&mut cli).unwrap();
87//! # assert_eq!(num, 55);
88//! # }
89//! ```
90//!
91//! ```text,ignore
92//! error: in lua: `a` is not defined (undefined_variable)
93//!    --> src/lib.rs:80:10
94//!    |
95//! 10 |   return a + 1
96//!    |          ^
97//!
98//!    error: aborting due to previous error
99//! ```
100//!
101//! # Capturing a variable
102//!
103//! `@` with an identifier allows to capture a Rust variable in the script. It allows to capture any types which implement [`serde::Serialize`][].
104//!
105//! ```rust
106//! # use redis_lua::lua;
107//! #
108//! # fn main() {
109//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
110//! #
111//! let x = 10;
112//!
113//! let script = lua!(return @x + 2);
114//! let num: usize = script.invoke(&mut cli).unwrap();
115//! assert_eq!(num, 12);
116//! # }
117//! ```
118//!
119//! # Argument substitution
120//!
121//! `$` with an identifier allows to substitute a variable before actually running the script. Same as `@`, any types which implement [`serde::Serialize`][] can be substituted.
122//!
123//! ```rust
124//! # use redis_lua::lua;
125//! #
126//! # fn main() {
127//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
128//! #
129//! let script = lua!(return $x + 2);
130//! let num: usize = script.x(30).invoke(&mut cli).unwrap();
131//! assert_eq!(num, 32);
132//! # }
133//! ```
134//!
135//! The difference from `@` is that the same script can be called multiple times with different values.
136//!
137//! ```rust
138//! # use redis_lua::lua;
139//! #
140//! # fn main() {
141//! # let mut cli = redis::Client::open("redis://localhost").unwrap();
142//! #
143//! let script = lua!(return $x + 2);
144//!
145//! for i in 0..10 {
146//!     let num: usize = script.clone().x(i).invoke(&mut cli).unwrap();
147//!     assert_eq!(num, i + 2);
148//! }
149//! # }
150//! ```
151//!
152//! The script object is clonable if all the variables it captures are clonable or it captures no variables.
153//!
154//! # Type conversion
155//!
156//! `@` and `$` allow to pass Rust variables to Lua scripts. Primitive types and strings are converted to
157//! the corresponding primitive types/strings in Lua scripts.
158//! Non-empty byte sequences (e.g. `Vec<u8>`, `&[u8]`) are converted to a Lua string.
159//! If the sequence is empty, it's converted to an empty table.
160//!
161//! Complicated types such as structs, tuples, maps and non-u8 vectors are converted to Lua tables.
162//! The name of struct members become the key of tables.
163//!
164//! # Limitation
165//!
166//! * The comment `--` is available only in nightly.
167//! * The warnings are available only in nightly. All the warnings are treated as errors in stable.
168//!
169
170use proc_macro_hack::proc_macro_hack;
171
172mod script;
173mod types;
174
175pub use futures;
176pub use redis;
177pub use serde;
178
179/// Macro to embed Lua script in Rust code.
180#[proc_macro_hack]
181pub use redis_lua_macro::lua;
182
183/// Macro to convert Lua script to string.
184#[proc_macro_hack]
185pub use redis_lua_macro::lua_s;
186
187pub use script::{gen_script, Info, Script, ScriptJoin, TakeScript};
188
189pub use types::{script_arg, ScriptArg};