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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! //! redis-lua is a Lua scripting helper for [`redis-rs`](https://github.com/mitsuhiko/redis-rs) //! //! redis-lua allows to insert Redis Lua scripts in Rust code in safer manner. The key features of redis-lua are: //! //! * Compile-time lint for Redis Lua scripts. //! * Capturing Rust variables in Lua scripts. //! * Safe argument substitution. //! * Safely joining multiple Lua scripts. //! //! # Invoke a Lua script //! //! [`lua`][] macro allows to create the Lua script. The script object implements [`Script`][] trait. //! The return value from the script can be converted to any types which implement [`redis::FromRedisValue`][]. //! //! ```rust //! use redis_lua::lua; //! //! # fn main() { //! let mut cli = redis::Client::open("redis://localhost").unwrap(); //! //! let script = lua!(return 1 + 2); //! let num: usize = script.invoke(&mut cli).unwrap(); //! assert_eq!(num, 3); //! # } //! ``` //! //! Any Lua syntax supported by Redis Lua is usable. //! //! * if-else //! //! ```rust //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! # let script = //! lua!( //! if 3 > 1 then //! return 3 //! else //! return 1 //! end //! ); //! # let num: usize = script.invoke(&mut cli).unwrap(); //! # assert_eq!(num, 3); //! # } //! ``` //! //! * for-loop //! //! ```rust //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! # let script = //! lua!( //! local sum = 0 //! for i=1,10 do //! sum = sum + i //! end //! return sum //! ); //! # let num: usize = script.invoke(&mut cli).unwrap(); //! # assert_eq!(num, 55); //! # } //! ``` //! //! # Error reporting //! //! Errors in Lua scripts (such as undefined variables) are detected at compile time. //! //! ```rust,ignore //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! # let script = //! lua!( //! return a + 1 //! ); //! # let num: usize = script.invoke(&mut cli).unwrap(); //! # assert_eq!(num, 55); //! # } //! ``` //! //! ```text,ignore //! error: in lua: `a` is not defined (undefined_variable) //! --> src/lib.rs:80:10 //! | //! 10 | return a + 1 //! | ^ //! //! error: aborting due to previous error //! ``` //! //! # Capturing a variable //! //! `@` with an identifier allows to capture a Rust variable in the script. It allows to capture any types which implement [`serde::Serialize`][]. //! //! ```rust //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! let x = 10; //! //! let script = lua!(return @x + 2); //! let num: usize = script.invoke(&mut cli).unwrap(); //! assert_eq!(num, 12); //! # } //! ``` //! //! # Argument substitution //! //! `$` with an identifier allows to substitute a variable before actually running the script. Same as `@`, any types which implement [`serde::Serialize`][] can be substituted. //! //! ```rust //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! let script = lua!(return $x + 2); //! let num: usize = script.x(30).invoke(&mut cli).unwrap(); //! assert_eq!(num, 32); //! # } //! ``` //! //! The difference from `@` is that the same script can be called multiple times with different values. //! //! ```rust //! # use redis_lua::lua; //! # //! # fn main() { //! # let mut cli = redis::Client::open("redis://localhost").unwrap(); //! # //! let script = lua!(return $x + 2); //! //! for i in 0..10 { //! let num: usize = script.clone().x(i).invoke(&mut cli).unwrap(); //! assert_eq!(num, i + 2); //! } //! # } //! ``` //! //! The script object is clonable if all the variables it captures are clonable or it captures no variables. //! //! # Type conversion //! //! `@` and `$` allow to pass Rust variables to Lua scripts. Primitive types and strings are converted to //! the corresponding primitive types/strings in Lua scripts. //! Non-empty byte sequences (e.g. `Vec<u8>`, `&[u8]`) are converted to a Lua string. //! If the sequence is empty, it's converted to an empty table. //! //! Complicated types such as structs, tuples, maps and non-u8 vectors are converted to Lua tables. //! The name of struct members become the key of tables. //! //! # Limitation //! //! * The comment `--` is available only in nightly. //! * The warnings are available only in nightly. All the warnings are treated as errors in stable. //! use proc_macro_hack::proc_macro_hack; mod script; mod types; pub use futures; pub use redis; pub use serde; /// Macro to embed Lua script in Rust code. #[proc_macro_hack] pub use redis_lua_macro::lua; /// Macro to convert Lua script to string. #[proc_macro_hack] pub use redis_lua_macro::lua_s; pub use script::{gen_script, Info, Script, ScriptJoin, TakeScript}; pub use types::{script_arg, ScriptArg};