Rust
About Rust
● New systems programming language by Mozilla.
● Designed to write secure code:
● Memory safety
● Thread safety
● Performance similar to C++
Hello, world!
fn main() {
println!(“Hello, world!”);
}
$ rustc hello.rs
$ ./hello
Hello, world!
Cargo
Cargo.toml
[package]
name = "program"
version = "0.1.0"
authors = ["John D <john.d@test.com>"]
[features]
default = [ ]
[dependencies]
num = "0.1.27"
Commands
$ cargo build
$ cargo test
$ cargo run
$ cargo new title [--bin]
Tool used for downloading dependencies, building dependencies and
building our program.
Syntax
fn increase(x: i32) -> i32 {
x + 1
}
fn swap(tuple: (i32, i32)) -> (i32, i32)
{
let (x, y) = tuple;
(y, x)
}
fn main() {
println!("{}", increase(10));
let my_tuple = (10, 20);
println!("{:?}", swap(my_tuple));
}
$ rustc syntax.rs
$ ./syntax
11
(20, 10)
Variable bindings
A 'let' expression is a pattern:
let(x, y) = (42, 24); // x = 42, y = 24
Variable bindings are immutable by default:
let x = 42;
x = 10;// error
let mut x = 42;
Type inference:
let x: i32 = 10; // Same as let x = 10;
Stack and Heap
fn main() {
let x = Box::new(5);
let y = 42;
let z = &x;
}
Box<T> implements Drop, it is freed when it goes out of
scope
Address Name Value
2^30
...
5
2 z → 0
1 y 42
0 x → 2^30
Vector
● Provided by the std library
● Growable (dynamic)
● Can implement any type: Vec<T>
let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
let mut my_vector: Vec<u8> = Vec::new();
let v = vec![0; 10];
for i in &v {
println!("Reference to {}", i);
}
for point in fractal.iter() {
if *point == 0 {…}
}
Structs and enums
STRUCT
struct Color {r: i32, g: i32, b: i32 }
fn main() {
let mut color: Color = Color { r: 255, g: 0, b: 0 };
color.g = 255;
println!("r: {}, g: {}, b: {}", color.r, color.g, color.b);
}
ENUM
#[derive(Debug)]
enum OperationError {
DivisionByZero,
UnexpextedError,
Indetermination,
}
fn division(n: f64, d: f64) -> Result<f64, OperationError> {...}
Pattern matching
let x = 3;
match x {
1 => println!("one"),
2 | 3 => println!("two or three"),
x @ 4..10 => println!(“say {}”, x),
_ => println!("i can't count that much"),
}
Result<T, E>
To manage errors, we can use the type system:
enum Result<T, E> {
Ok(T),
Err(E)
}
// Result<T, String>
fn division(num: f64, den: f64) -> Result<f64, String> {
if den == 0.0 {
Err(“Error”)
} else {
Ok(num / den)
}
}
Ownership
Variable bindings imply there is an owner to an asset
fn foo() {
let v = vec![1, 2, 3];
}
1) v in scope: Vec<i32> is created
2) Vector lives in the heap
3) Scope ends: v is freed, heap
allocated vector is cleaned.
There is only one binding to any asset. Lifetimes and transferring
ownership must be considered.
fn read_vector(vec: Vec<i32>) {
println!("{:?}", vec);
}
fn main() {
let my_vector = vec!(1, 3, 5, 7);
read_vector(my_vector);
println!("{:?}", my_vector); // error
}
Ownership
Give back ownership:
fn read_vector(vec: Vec<i32>) -> Vec<i32> {
println!("{:?}", vec);
vec
}
Borrowing (pass by reference):
fn read_vector(vec: &Vec<i32>) {
println!("{:?}", vec);
}
fn main() {
let my_vector = vec!(1, 3, 5, 7);
...
}
Ownership
Mutable reference: &mut
fn add_to_vector(vec: &mut Vec<i32>) {
vec.push(10);
}
fn main() {
let mut my_vector = vec!(1, 3, 5, 7);
add_to_vector(&mut my_vector);
println!("{:?}", my_vector);
}
● Any borrow's scope may not last longer than the owner
● Can exist many immutable borrows, (&x)
● Only one mutable reference (&mut x)
Traits
// TRAIT: Tells about a functionality a type has to provide
trait Dimensional {
fn area(&self) -> i32;
}
// Function for any type that implements the Dimensional trait
fn print_area<T: Dimensional>(object: T) {
println!("Area: {}", object.area());
}
struct Rectangle {x1: i32, y1: i32, x2: i32, y2: i32,}
impl Dimensional for Rectangle {
fn area(&self) -> i32 {
(self.x2 - self.x1) * (self.y2 - self.y1)
}
}
fn main() {
let r = Rectangle { x1: 0, x2: 4, y1: 0, y2: 2, };
print_area(r);
}
Closures
● Anonymous functions
● Rust imposes less restrictions about type annotations:
● Argument types and return types can be inferred
● May be multi-line, with statements between { }
fn main() {
let multiply = |x, y| x * y;
let sum_squares = |x: i32, y: i32| -> i32 {
let x = x * x;
let y = y * y;
x + y
};
println!("{:?}", multiply(2, 3));
println!("{:?}", sum_squares(2, 3));
}
Threading (spawning)
● A thread can be spawned with thread::spawn
● Accepts a closure and returns a handle
● Handles can be error checked with the Result Enum
use std::thread;
fn main() {
let handle = thread::spawn(|| "Hello".to_string());
match handle.join() {
Ok(x) => println!("{}", x),
Err(e) => println!("{:?}", e),
}
}
Other features
● Foreign Function Interface in 2 directions:
● Can call C code into Rust
● Can call Rust into other programs
● Conditional compilation by passing flags and assisted by Cargo
[features]
secure-password = ["bcrypt"]
● Use of 'raw pointers' (marked as unsafe to the compiler)
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
Rust projects
● Maidsafe (http://maidsafe.net/)
“ MaidSafe is a fully decentralized platform on which
application developers can build decentralized applications”
● Crates.io (https://crates.io/)
A catalog with Rust crates
● Servo (https://github.com/servo/servo)
“Servo is a prototype web browser engine written in the Rust
language. It is currently developed on 64bit OS X, 64bit Linux,
Android, and Gonk (Firefox OS).”

Short intro to the Rust language

  • 1.
  • 2.
    About Rust ● Newsystems programming language by Mozilla. ● Designed to write secure code: ● Memory safety ● Thread safety ● Performance similar to C++
  • 3.
    Hello, world! fn main(){ println!(“Hello, world!”); } $ rustc hello.rs $ ./hello Hello, world!
  • 4.
    Cargo Cargo.toml [package] name = "program" version= "0.1.0" authors = ["John D <john.d@test.com>"] [features] default = [ ] [dependencies] num = "0.1.27" Commands $ cargo build $ cargo test $ cargo run $ cargo new title [--bin] Tool used for downloading dependencies, building dependencies and building our program.
  • 5.
    Syntax fn increase(x: i32)-> i32 { x + 1 } fn swap(tuple: (i32, i32)) -> (i32, i32) { let (x, y) = tuple; (y, x) } fn main() { println!("{}", increase(10)); let my_tuple = (10, 20); println!("{:?}", swap(my_tuple)); } $ rustc syntax.rs $ ./syntax 11 (20, 10)
  • 6.
    Variable bindings A 'let'expression is a pattern: let(x, y) = (42, 24); // x = 42, y = 24 Variable bindings are immutable by default: let x = 42; x = 10;// error let mut x = 42; Type inference: let x: i32 = 10; // Same as let x = 10;
  • 7.
    Stack and Heap fnmain() { let x = Box::new(5); let y = 42; let z = &x; } Box<T> implements Drop, it is freed when it goes out of scope Address Name Value 2^30 ... 5 2 z → 0 1 y 42 0 x → 2^30
  • 8.
    Vector ● Provided bythe std library ● Growable (dynamic) ● Can implement any type: Vec<T> let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> let mut my_vector: Vec<u8> = Vec::new(); let v = vec![0; 10]; for i in &v { println!("Reference to {}", i); } for point in fractal.iter() { if *point == 0 {…} }
  • 9.
    Structs and enums STRUCT structColor {r: i32, g: i32, b: i32 } fn main() { let mut color: Color = Color { r: 255, g: 0, b: 0 }; color.g = 255; println!("r: {}, g: {}, b: {}", color.r, color.g, color.b); } ENUM #[derive(Debug)] enum OperationError { DivisionByZero, UnexpextedError, Indetermination, } fn division(n: f64, d: f64) -> Result<f64, OperationError> {...}
  • 10.
    Pattern matching let x= 3; match x { 1 => println!("one"), 2 | 3 => println!("two or three"), x @ 4..10 => println!(“say {}”, x), _ => println!("i can't count that much"), }
  • 11.
    Result<T, E> To manageerrors, we can use the type system: enum Result<T, E> { Ok(T), Err(E) } // Result<T, String> fn division(num: f64, den: f64) -> Result<f64, String> { if den == 0.0 { Err(“Error”) } else { Ok(num / den) } }
  • 12.
    Ownership Variable bindings implythere is an owner to an asset fn foo() { let v = vec![1, 2, 3]; } 1) v in scope: Vec<i32> is created 2) Vector lives in the heap 3) Scope ends: v is freed, heap allocated vector is cleaned. There is only one binding to any asset. Lifetimes and transferring ownership must be considered. fn read_vector(vec: Vec<i32>) { println!("{:?}", vec); } fn main() { let my_vector = vec!(1, 3, 5, 7); read_vector(my_vector); println!("{:?}", my_vector); // error }
  • 13.
    Ownership Give back ownership: fnread_vector(vec: Vec<i32>) -> Vec<i32> { println!("{:?}", vec); vec } Borrowing (pass by reference): fn read_vector(vec: &Vec<i32>) { println!("{:?}", vec); } fn main() { let my_vector = vec!(1, 3, 5, 7); ... }
  • 14.
    Ownership Mutable reference: &mut fnadd_to_vector(vec: &mut Vec<i32>) { vec.push(10); } fn main() { let mut my_vector = vec!(1, 3, 5, 7); add_to_vector(&mut my_vector); println!("{:?}", my_vector); } ● Any borrow's scope may not last longer than the owner ● Can exist many immutable borrows, (&x) ● Only one mutable reference (&mut x)
  • 15.
    Traits // TRAIT: Tellsabout a functionality a type has to provide trait Dimensional { fn area(&self) -> i32; } // Function for any type that implements the Dimensional trait fn print_area<T: Dimensional>(object: T) { println!("Area: {}", object.area()); } struct Rectangle {x1: i32, y1: i32, x2: i32, y2: i32,} impl Dimensional for Rectangle { fn area(&self) -> i32 { (self.x2 - self.x1) * (self.y2 - self.y1) } } fn main() { let r = Rectangle { x1: 0, x2: 4, y1: 0, y2: 2, }; print_area(r); }
  • 16.
    Closures ● Anonymous functions ●Rust imposes less restrictions about type annotations: ● Argument types and return types can be inferred ● May be multi-line, with statements between { } fn main() { let multiply = |x, y| x * y; let sum_squares = |x: i32, y: i32| -> i32 { let x = x * x; let y = y * y; x + y }; println!("{:?}", multiply(2, 3)); println!("{:?}", sum_squares(2, 3)); }
  • 17.
    Threading (spawning) ● Athread can be spawned with thread::spawn ● Accepts a closure and returns a handle ● Handles can be error checked with the Result Enum use std::thread; fn main() { let handle = thread::spawn(|| "Hello".to_string()); match handle.join() { Ok(x) => println!("{}", x), Err(e) => println!("{:?}", e), } }
  • 18.
    Other features ● ForeignFunction Interface in 2 directions: ● Can call C code into Rust ● Can call Rust into other programs ● Conditional compilation by passing flags and assisted by Cargo [features] secure-password = ["bcrypt"] ● Use of 'raw pointers' (marked as unsafe to the compiler) let x = 5; let raw = &x as *const i32; let points_at = unsafe { *raw }; println!("raw points at {}", points_at);
  • 19.
    Rust projects ● Maidsafe(http://maidsafe.net/) “ MaidSafe is a fully decentralized platform on which application developers can build decentralized applications” ● Crates.io (https://crates.io/) A catalog with Rust crates ● Servo (https://github.com/servo/servo) “Servo is a prototype web browser engine written in the Rust language. It is currently developed on 64bit OS X, 64bit Linux, Android, and Gonk (Firefox OS).”