error messages • Rust has top-notch tooling: • Integrated package manager and build tool (Cargo) • Support for all major editors and IDEs • Rust was the “most loved programming language” in the Stack Overflow Developer Survey for 2016, 2017, and 2018 What is Rust?
space as Redis • A bad memory access can crash the whole process • Memory leaks will waste precious Redis memory • We need safe memory usage! • This is the primary issue that Rust addresses Why use Rust for writing Redis modules?
module will slow down Redis • We need performance! • Rust’s safety does not mean reduced performance • We can have nice things Why use Rust for writing Redis modules?
1982 1988 1995 2001 2007 2013 2019 C 1972 • First there was C • Used to make a portable version of Unix • Relatively small and simple language • Runs everywhere
1976 1982 1988 1995 2001 2007 2013 2019 C 1972 • Features raw pointers, raw memory access, pointer arithmetic • Memory management is handled explicitly by the developer • No standard way to handle errors • Writing safe code requires significant expertise
} Person; int main() { Person person = { .name="Joe", .age=25 }; Person *somebody = &person; printf("%s is %d\n", somebody ->name, somebody ->age); } What does Rust look like? Let’s start with some C first
} fn main() { let person = Person { name: "Joe", age: 25 }; let somebody = &person; println!("{} is {}", somebody.name, somebody.age); } The equivalent code in Rust
Can create new syntax in the language • Hygienic (like Scheme, unlike C) • Works on tokens in the AST presented by let languages = vec!["C", "C ++", "Rust"]; Avoiding the boilerplate: Macros!
f: Result<File, Error> = File ::open("foo"); match f { Ok(file) => { file.bytes(); } Err(err) => { println!("{}", err); } } Using the Result with pattern matching
write pure Rust code without needing unsafe • Hide the C interfaces behind a pure Rust API • Have an API that is idiomatic Rust and doesn’t rely on C-like types (such as an argv/argc pair) • Add a high-level abstraction over the Rest Modules API Low-level bindings are not user-friendly
define a pure Rust function that is then wrapped with a C-compatible callback that Redis can call • Macros to the rescue How do we avoid writing lots of boilerplate code?
determines lifetimes of variables (no use-after-free possible) • No null references • Dereferencing a raw pointer is unsafe • Mutable static variables are unsafe Rust: Safety
code is simple • Our main task has been (and still is): • Come up with a clean, safe and idiomatic Rust API for modules • Hide all the ugly stuff from the module developer What do we need?
Servo, said: • “All of [ our security critical bugs with Firefox WebAudio ] were array out of bounds or use-after-free errors, and all of them would have been prevented by the Rust compiler” Why Rust?