<style> .slides { /* width: 100% !important; */ } .reveal section img { background:none; border:none; box-shadow:none; } .reveal pre { box-shadow: none; overflow: visible; } .reveal pre code { max-height: 700px; background: white; color: black; box-shadow: none; overflow: visible; } </style> ### whoami - 👨🏽‍💻 Noah Hüsser - 🎓 BSc in Electrical Engineering - 👷 Rust Developer - 🥋 Ju Jitsu & 🏃 Running --- ![technokrat.ch](https://technokrat.ch/static/img/svg_banner-light.svg) --- # Rust ![Rust](https://upload.wikimedia.org/wikipedia/commons/d/d5/Rust_programming_language_black_logo.svg) --- ### Rust solves 70% of your security critical bugs out of the box! Note: - Common catchphrase - Everybody that heard about Rust heard about this --- ![](https://i.imgur.com/icCZri1.png) source: https://www.chromium.org/Home/chromium-security/memory-safety Note: - Graph from Chrome 2015-2020 - Same holds true for Windows - And any CVEs in general --- ### Rust is much more than that! Note: - Rust is much more - Beloved for many features - Which I am going to talk about in the next 30 minutes or so --- ### Rust in production Mozilla (Firefox), Dropbox (Sync Engine), Microsoft (WinRT), Cloudflare (WireGuard), Discord (efficent Channel User Store), ARM (Development of AArch64) Note: - Many big players are starting to adopt Rust - Or are invested heavily already - Firefox (Stylo, Servo) - Dropbox (core of their services!) - Microsoft pushes Rust big time internally, provides complete WinRT API - CloudFlare (WireGuard implementation) - Discord (Idle channel janitor) - ARM provides builders for the AArch64 tests --- ### Why is it so popular? _“The short answer is that Rust solves pain points present in many other languages, providing a solid step forward with a limited number of downsides.”_ - Jake Goulding Note: - Rust has taken the number one spot of the most loved language amongst StackOverflow users (65k participants) since 2016. - Shepmaster explains it in a simple sentence. --- ### Rust is versatile! --- #### Systems programming - Memory safety - Thread safety - Zero cost abstractions - Fast! Note: - Applicable in pretty much any field where programming is used - Reuseability is great - Same benefits that made JS popular for Web front and backend --- #### Embedded programming - Suitable for embedded programming - close-to-C perfromance - concepts like async await very promising - Interrupt safety through static analysis --- #### GPU / Game programming ![](https://github.com/Yatekii/sailor/blob/master/doc/img/screenshot.png?raw=true) --- #### Web programming - Compiles to WASM - Libraries to interface JS - Reactive frameworks like Yew similar to React, Vue, etc. - Reuse types Note: - Applicable in pretty much any field where programming is used - Reuseability is great - Same benefits that made JS popular for Web front and backend --- ### Rust is easy to use! --- ### It starts with the tooling - rustup (a toolchain manager) - cargo (a package manager) - crates.io (package registry) Note: - Easy to use starts with the installer - No wrong turns to be taken, no signups, etc. - All batteries included - The Rust project provides a one shop experience --- #### rustup ``` curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` - Selection of stable, beta and nightly channel - Selection of compilation target - Easy cross compilation - Selective overrides - Automatic downloads of required toolchains - Installs cargo & rustc --- #### cargo - Package manager - Build tool - Test runner - Benchmark runner - Easy extension possibilities - Documentation builder --- #### cargo - package manager & build tool - One central file per project - package dependencies - metadata describing your package - conditional compiling flags - typed! - dependencies - Uses semantic versioning --- #### cargo - package manager & build tool (cont.) - Automatically fetches and builds the packages defined in your config - Support for various types of package sources - crates.io registry - Private registries - Git - Local --- #### cargo - Cargo.toml ```toml [package] name = "backend" version = "0.1.0" authors = ["Noah Hüsser"] edition = "2018" readme = "../README.md" categories = ["web", "backend"] keywords = ["time-tracking", "web"] license = "MIT OR Apache-2.0" [dependencies] rocket = { git = "https://github.com/SergioBenitez/Rocket.git" } diesel = { version = "1.4.5", features = ["sqlite", "chrono"] } serde = { version = "*", features = ["derive"] } ``` --- #### cargo - test runner - Unit tests are first class citizen - Can be executed directly from cargo - `cargo test` - Can be enabled selectively - Can be executed on remote targets with the right tools. --- #### cargo flash ``` ➜ cargo flash --release --example blinky --chip nrf52840 Finished release [optimized] target(s) in 0.02s Flashing /home/yatekii/repos/probe-rs/nRF52840-DK/target/thumbv7em-none-eabihf/release/examples/blinky Erasing sectors ✔ [00:00:00] [############] 8.00KB/ 8.00KB @ 16.95KB/s (eta 0s ) Programming pages ✔ [00:00:00] [############] 8.00KB/ 8.00KB @ 6.34KB/s (eta 0s ) ``` Note: - cargo flash is an example of a cargo extension for embedded development - can directly access the cargo artifacts - can access cargo metadata - integrates seamlessly with the cargo experience --- ### Rust language features --- ### Basics - C-like syntax - Everything must be initialized at all times - Type safety - Traits (Interfaces) - Functional concepts --- ### Type inference ```rust struct T { a: u32 } let t = T { a: 42 }; // t gets type T assigned let a = 42; // Picks any suitable integer type for a let x: u32 = 1337; let mut vec = Vec::new(); // vec could be any Vec<T> vec.push(x); // now the compiler knows that vec is Vec<u32>! ``` Note: - Type inference to reduce code you have to write - Works oftentimes, sometimes the compiler has to be helped - Works in very complex code structures too! --- ### Iterators ```rust for i in 1..=100 { if i % 15 == 0 { println!("Fizz Buzz"); } else if i % 3 == 0 { println!("Fizz"); } else if i % 5 == 0 { println!("Buzz"); } else { println!("{}", i); } } ``` Note: - Just like known from C++ & Python - Compiled down to simple loops - Zero overhead - Helps ensure memory safety - No boundary checks required - Oftentimes faster than manually looping - Downside: Can be slow in debug mode without optimizations - Expressivity does not suffer in exchange for speed --- ### Zero Cost abstractions - Freely use any abstraction without any penalty - Map & Closure instead of loop - Iterator instead of loop - Typestates - Zero sized types - Type markers for checks purely during compiletime - Completely vanish in the binary --- ### Trait based generics ```rust trait Display { fn display(&self) -> String { "Hello World".to_string() } } pub fn print_name<T: Display>(value: T) { println!("{}", value.display()); } ``` Note: - Generics are known as templates in C++ - Less weird intricacies than C++ - Generic parameters can be constrained in various ways - Allows us to write better useable code without sacrificing speed - Generics are a good alternative to polymorphism which is not present in Rust - Trait objects can be generated, which are opaque values implementing a trait --- ### Pattern matching ```rust struct RGB { r: u8, g: u8, b: u8 }; let rgb = RGB { r: 42, g: 42, b: 42 }; let RGB { r, g, .. } = rgb; println!("{}", r); ``` Note: - Can be used to extract values - Known from functional languages - Complex structures can be easily decomposed and single values can be extracted improving readability --- ### Algebraic Data Types ```rust enum Option<T> { Some(T), None, } fn unwrap<T>(value: Option<T>) -> T { match value { Some(t) => t, None => panic!("None value encountered!"), } } ``` Note: - Also known as enums - Awesome to express closed treelike data structures - Perfect for parsing trees! - Makes it possible to make initialization a must! - No nullptrs because of Option - Result type replaces exceptions --- ### No null In Python ```python let v = None for i in very_long_loop(): do_things() v.a = 4 # Program dies after running for a long time! ``` In Rust ```rust let v = None; for i in very_long_loop() { do_things(); } v.a = 4; // Does not compile! ``` --- ### No exceptions In Python ```python def foo: raise Exception("Sorry, no numbers below zero") ``` Note: - Nothing in this signature tells us about this code flow! - Result replaces exceptions - Makes Rust suitable for embedded! - No forgetting to handle results! - No unseen control flow - Can be cumbersome to use at times - large or many error types - Huge improvements in the makings - Different major libs/frameworks to do error-handling --- ### No exceptions ```rust enum Result<T, E> { Ok(T), Err(E), } fn unwrap<T, E>(value: Result<T, E>) -> T { match value { Ok(t) => t, Err(_) => panic!("Err value encountered!"), } } ``` Note: - Nothing in this signature tells us about this code flow! - Result replaces exceptions - Makes Rust suitable for embedded! - No forgetting to handle results! - No unseen control flow - Can be cumbersome to use at times - large or many error types - Huge improvements in the makings - Different major libs/frameworks to do error-handling --- ### Ownership - Guaranteed memory safety - Data race free - Minimal runtime, no GC - Move Semantics - `unsafe {} == yolo` --- ### Ownership - A simple example ```rust let a = Vec::<u32>::new(); // a owns the value of the Vec<T>. let b = a; // a is moved into b; a can no longer be accessed! fn foo(b: Vec<u32>) {} foo(b); // b is moved into x foo(b); // does not work! b is moved on the line before. fn bar(b: &Vec<u32>) {} let c = 42; bar(&c); // c is borrowed immutably for the duration of y. bar(&c); // c can be borrowed again, because the first call to y() terminated! ``` --- ### Ownership - Locks ```rust let a = Arc::new(Mutex::new(42)); thread::spawn(move || { for i in 1..*a.lock().unwrap() { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } }).join(); ``` Note: - Locks are optional in other languages - rustc enforces this. - Wait but couln't we just use a &ref? - It does not let you borrow a value longer than it lives. - We could move the value to the thread, but imagine we had two threads. - We can only move it once. --- ### C ABI -> efficient C bindings ```rust #[link(name = "my_c_library")] extern "C" { fn my_c_function(x: i32) -> bool; } #[no_mangle] pub extern fn callable_from_c(x: i32) -> bool { x % 3 == 0 } ``` Note: - Stolen from the rust Docs - Works both ways - Helper libs for ffi (libc, std::ffi) - Generators (bindgen, cbindgen) --- ### Inline documentation ```rust /// Returns a person with the name given them /// /// # Arguments /// /// * `name` - A string slice that holds the name of the person pub fn new(name: &str) -> Person { Person { name: name.to_string(), } } /// Gives a friendly hello! /// /// Says "Hello, [name]" to the `Person` it is called on. pub fn hello(& self) { println!("Hello, {}!", self.name); } ``` Note: - Rust features inline documentation - All items can be annotated with /// - cargo can automatically generate interactive HTML docs - Annotates everything with the doc-comments - Doc comments support markdown --- ### Inline documentation - generated ![](https://i.imgur.com/eatTQ97.png) Note: - Ths is how the generated docs look - Can be styled with CSS - Interactive --- ### Inline documentation - doc tests ```rust /// Returns a person with the name given them /// /// # Arguments /// /// * `name` - A string slice that holds the name of the person /// /// # Examples /// /// ``` /// // You can have rust code between fences inside the comments /// // If you pass --test to `rustdoc`, it will even test it for you! /// use doc::Person; /// let person = Person::new("name"); /// ``` pub fn new(name: &str) -> Person { Person { name: name.to_string(), } } ``` Note: - All the rust doc examples are doctested - If the doctests fail the crate wont build - This results in always up2date examples in libraries! - Items can be hidden (main e.g.) - Items can be marked as no run --- ### Nice error messages ``` error[E0308]: mismatched types --> src/main.rs:2:21 | 2 | let s: String = "Hello World!"; | ------ ^^^^^^^^^^^^^^ | | | | | expected struct `std::string::String`, found `&str` | | help: try using a conversion method: `"Hello World!".to_string()` | expected due to this ``` Note: - The compiler fights with you agains your issues - Instead of fighting against you on the side of your issues - From simple help messages - To complicated borrowchecker hints! --- ### Macros ```rust macro_rules! vec { ( $x:expr ) => { { let mut temp_vec = Vec::new(); temp_vec.push($x); temp_vec } }; } vec!(42); ``` Note: - Macros have more or less a sane syntax with no intricacies - Macro hygiene (no outside names/symbols inside macros) - Signature overloading - typed parameters! token trees, expressions, types, etc. --- ### Procedural macros ```rust #[derive(ToString)] struct Struct { value: u32 }; ``` --- ### Procedural macros ```rust let AST = parse_ast("struct Struct { value: u32 };"); let ToString = compile(ToString); let AST = ToString(AST); println!("{}", ast); ``` --- ### Procedural macros ```rust struct Struct { value: u32 }; impl ToString for Struct { fn to_string(&self) -> String { format!("Struct {{ value: {} }}", self.value) } } ``` Note: - Powerful code generators - Small Rust programs that are compiled during the compilation process - AST is passed to those programs - AST is transformed by those programs and returned - Which then is compiled! - Can effectively extend the language syntax - imagine typed HTML --- # Thank You! #### Questions? https://github.com/Yatekii [nh@technokrat.ch](mailto:nh@technokrat.ch) https://technokrat.ch
{"metaMigratedAt":"2023-06-15T12:23:05.334Z","metaMigratedFrom":"YAML","title":"Rust ![Rust](https://upload.wikimedia.org/wikipedia/commons/d/d5/Rust_programming_language_black_logo.svg)","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"theme\":\"white\",\"slideNumber\":true,\"height\":1000}","contributors":"[{\"id\":\"1e163eae-4cb6-4df5-92cc-f645e73b0bce\",\"add\":23774,\"del\":9110}]"}
    333 views