• Rust and Elasticsearch Trainer
• Event organiser
• Ruby Programmer since 2003
• Rust Programmer since 2013
• CEO asquera GmbH
Slide 4
Slide 4 text
• Community person
• Rust/Search Meetups
• eurucamp/jrubyconf.eu
• RustFest
• https://isleofruby.org/
Slide 5
Slide 5 text
Part of the global
Rust community team
Slide 6
Slide 6 text
As a hobby, I shoot arrows at stuff
Slide 7
Slide 7 text
Rust as a CLI
language
Slide 8
Slide 8 text
What is
Rust?
Slide 9
Slide 9 text
• new systems programming language
• powers and was developed in along
with Servo, a new browser engine
• by Mozilla and the Community
• First stable release May 15th, 2015
Slide 10
Slide 10 text
https://www.rust-lang.org/friends.html
Slide 11
Slide 11 text
Providing an alternative to C/C++,
but also higher-level languages.
Slide 12
Slide 12 text
• Safe
• Concurrent
• Fast
Slide 13
Slide 13 text
It’s generally perceived that
safety, especially memory-safety
comes at a runtime cost.
Slide 14
Slide 14 text
• Safe
• Concurrent
• Fast
Slide 15
Slide 15 text
Pick Three
Slide 16
Slide 16 text
Core features
Slide 17
Slide 17 text
• Static type system with local type
inference
• Explicit mutability
• Zero-cost abstractions
• Runtime-independent concurrency
safety
Slide 18
Slide 18 text
• Errors are values
• No null
• Static automatic memory manage-
ment
• No garbage collection
Slide 19
Slide 19 text
A short introduction
Slide 20
Slide 20 text
extern crate tempdir;
use tempdir::*;
use std::fs::File;
fn main() {
let tempdir = TempDir::new("goto-berlin");
let mut tempfile = match tempdir {
Ok(dir) => {
File::create(
dir.path().join("tmpfile")
)
}
Err(_) => { panic!("Couldn’t open tempdir") }
}
do_something(&mut tempfile);
// look, no close necessary!
}
Slide 21
Slide 21 text
Base concept:
Mutability
Slide 22
Slide 22 text
struct InnerData {
val: i32
}
struct Data {
inner: InnerData
}
fn main() {
let d = Data { inner: InnerData { val: 41 }};
d.inner.val = 42;
// error: cannot assign to immutable field `d.inner.val`
}
Slide 23
Slide 23 text
struct InnerData {
val: i32
}
struct Data {
inner: InnerData
}
fn main() {
let mut d = Data { inner: InnerData { val: 41 }};
d.inner.val = 42;
}
Slide 24
Slide 24 text
Base concept:
Ownership & Borrowing
Slide 25
Slide 25 text
• Every piece of data is uniquely
owned
• Ownership can be passed
• When owned data reaches the end
of a scope, it is destructed
Slide 26
Slide 26 text
use std::fs::File;
use std::io::Write;
fn main() {
let file = File::open("test")
.expect("Unable to open file, bailing!");
take_and_write_to_file(file);
// take_and_write_to_file(file);
// ^^ Illegal
}
fn take_and_write_to_file(mut file: File) {
writeln!(file, "{}", "Hello #gotober!");
}
Slide 27
Slide 27 text
• Access can be borrowed (mutable
and immutable)
• You can borrow mutably once
• Or multiple times immutably
• Exclusive: mutable or immutable,
never both
Slide 28
Slide 28 text
Shared mutable state is an issue
even single-threaded applications!
Slide 29
Slide 29 text
use std::fs::File;
use std::io::Write;
fn main() {
let mut file = File::open("test")
.expect("Unable to open file, bailing!");
write_to_file(&mut file);
write_to_file(&mut file);
}
fn write_to_file(file: &mut File) {
writeln!(file, "{}", "Hello #gotober!");
}
Slide 30
Slide 30 text
fn main() {
let mut vector = vec![1,2,3];
let elem = &vector[1];
vector[2] = 4;
}
Slide 31
Slide 31 text
error[E0502]: cannot borrow `vector` as mutable
–> src/main.rs:4:5
|
3 | let elem = &vector[1];
| —— immutable borrow occurs h
4 | vector[2] = 4;
| ^^^^^^ mutable borrow occurs here
5 | }
| - immutable borrow ends here
Slide 32
Slide 32 text
Rust checks validity of all
references at compile-time.
Slide 33
Slide 33 text
struct Data<’a> {
inner: &’a i32
}
fn return_reference<’a>() -> Data<’a> {
let number = 4;
Data { inner: &number }
}
Slide 34
Slide 34 text
–> src/main.rs:8:20
|
8 | Data { inner: &number }
| ^^^^^^ does not live long
9 | }
| - borrowed value only lives until here
|
Slide 35
Slide 35 text
All Rust function signatures not only
signal data types, but also mutability,
ownership and interconnections
between input and output types.
Slide 36
Slide 36 text
100, 1000, 10.000 lines of called
code, Rust keeps these properties!
Slide 37
Slide 37 text
Abstractions
Rust provides higher-level abstractions
through Generics and Traits, similar
to C++ Templates or Java Generics.
Slide 38
Slide 38 text
Low-level
control & safety!
Slide 39
Slide 39 text
• Borrows boil down to pointers at
runtime
• Values are plain values just like in
e.g. C
• Optional unsafe sub-language
Slide 40
Slide 40 text
“ Safe code means you
can take better risks.”
– @QEDunham
Slide 41
Slide 41 text
"I stopped writing Python or Ruby, I
write my small tools in Rust now."
Slide 42
Slide 42 text
rustup
http://rustup.rs or
your package manager
Slide 43
Slide 43 text
rustup
rustup allows full management of
a Rust development toolchain,
including cross-compilation.
Slide 44
Slide 44 text
rustup
In general, it is recommendable
to target a rustc that is shipped
with your target system.
Slide 45
Slide 45 text
rustup
$ rustup install stable
Slide 46
Slide 46 text
Minimum version
The minimum version for the
following example is Rust 1.15.
Slide 47
Slide 47 text
Writing a small
CLI program
Slide 48
Slide 48 text
We’re currently collecting
community blogposts and I lost
count. Luckily, a kind soul offers
a JSON feed on readrust.net.
Quick error
handling in CLI
let file = File::open("foo").unwrap();
// This will quit if the File cannot be opened
Slide 52
Slide 52 text
Strings
Rust has 2 types of strings: &str and
String. The first is harder to use then
the second. They are compatible.
Slide 53
Slide 53 text
Quickly
handling Strings
At the beginning, whenever
you encounter &str and
are confused, use this:
let heap_allocated_string = "normal_string".to_string();
Slide 54
Slide 54 text
Task
A proper CLI tool that gets
the feed, parses it, prints it
in a nice, readable fashion.
Slide 55
Slide 55 text
readrust 0.1
Florian G.
Reads readrust.net
USAGE:
readrust [FLAGS] [OPTIONS]
FLAGS:
-c, –count Show the count of posts
-h, –help Prints help information
-V, –version Prints version information
OPTIONS:
-n, –number Only print the NUMBE
Slide 56
Slide 56 text
We need:
• Argument parser
• HTTP client
• JSON parser
• A pretty-printer
extern crate clap;
use clap::App;
fn main() {
let app = App::new("readrust")
.version("0.1")
.author("Florian G. ")
.about("Reads readrust.net")
.args_from_usage("-n, –number=[NUMBER] ’Only print
the NUMBER most recent posts’
-c, –count ’Show the
count of posts’");
let matches = app.get_matches();
}
Slide 63
Slide 63 text
$ cargo run – –help
readrust 0.1
Florian G.
Reads readrust.net
USAGE:
readrust [FLAGS] [OPTIONS]
FLAGS:
-c, –count Show the count of posts
-h, –help Prints help information
-V, –version Prints version information
OPTIONS:
-n, –number Only print the NUMBER most
recent posts
Slide 64
Slide 64 text
Well, that was quick.
Slide 65
Slide 65 text
HTTP
reqwest, the high-level http client
Slide 66
Slide 66 text
• Easy to use
• synchronous and asynchrous modes
• Documented
Using that
let feed = get_feed();
if matches.is_present("count") {
print_count(&feed);
}
Slide 79
Slide 79 text
Showing blog posts
Let’s use prettytable-rs. It prints
out data easily as a table.
Slide 80
Slide 80 text
prettytable-rs
• Easy to use
• Supports subtables and colours
• Documented
Slide 81
Slide 81 text
fn fn print_feed_table>(items: I) {
let mut table = prettytable::Table::new();
table.add_row(row!["Title", "Author", "Link"]);
for item in items {
let title = if item.title.len() >= 50 {
&item.title[0..50]
} else {
&item.title
};
table.add_row(row![title, item.author.name, item.url]);
}
table.printstd();
}
Slide 82
Slide 82 text
Using it
if matches.is_present("count") {
print_count(&feed);
} else {
let iter = feed.items.into_iter();
if let Some(string) = matches.value_of("number") {
let number = string.parse().unwrap();
print_feed_table(iter.take(number))
} else {
print_feed_table(iter)
}
}
Slide 83
Slide 83 text
We’re done
Slide 84
Slide 84 text
• A 79-line program
• With full build and dependency
tooling
• No typing ceremony except the
Feed definition
Slide 85
Slide 85 text
Advantages
Slide 86
Slide 86 text
• Easily shippable as a binary
• Full error handling (even if we just
bail!)
• Fully documented dependencies
Slide 87
Slide 87 text
When and why
to pick up Rust
• You want to learn something new
• You want that extra bit of perfor-
mance
• You want the control of C, but the
safety of Python
• You want to parallelise things
Slide 88
Slide 88 text
Learning experience
Rust takes around three
weeks to click in full.
Slide 89
Slide 89 text
Continuing
• Do proper error passing and central
handling
• Add logging (using... log!)
• Filter the items
• Make statistics over the items
Slide 90
Slide 90 text
Rust is a surprisingly productive
language with great compiler
diagnostics that scales from
lowlevel to "just quick" programs.
let counter = Counter { count: 0 };
for _ in 1..3 {
std::thread::spawn(move || {
increment(&mut counter);
// capture of moved value: `counter`
});
}
Slide 97
Slide 97 text
use std::rc::Rc;
let rc = Rc::new(Counter { count: 0 });
for _ in 1..3 {
let handle = rc.clone();
std::thread::spawn(move || {
// `std::rc::Rc` cannot be sent between
threads safely
increment(&mut handle);
});
}
Slide 98
Slide 98 text
use std::sync::{Arc,Mutex};
let rc = Arc::new(Mutex::new(Counter { count: 0 }));
for _ in 1..3 {
let handle = rc.clone();
std::thread::spawn(move || {
increment(&mut handle);
});
}
Slide 99
Slide 99 text
This example could be a
concurrency bug in many
languages, or even a double-free!
Slide 100
Slide 100 text
This analysis is purely static and
independent of concurrency primitive!
Rusts type system allows no data races.