Presentations
ptisnovs@redhat.com
Jazyk Rust se stává mezi programátory stále populárnější alternativou k C++ na straně jedné a k jazykům vybavených automatickým správcem paměti (GC) na straně druhé. Na této přednášce si řekneme, které vlastnosti Rustu zjednodušují jeho použití v produkčních systémech, které knihovny se nejčastěji používají a jak se aplikace psané v Rustu zabezpečují.
(D, Go, Nimrod…)
Jazyk Rust Go
Přístup moderní konzervativní
Syntaxe komplikovaná jednoduchá, minimalistická
Učící křivka menší sklon větší sklon
Učící křivka větší ampli. menší amplituda
Rychlost překladu pomalejší rychlejší
Backend LLVM vlastní
Linkování static/dynamic přes -buildmode (//export!!!)
Rychlost kódu rychlejší pomalejší
Typový systém rozsáhlý bez generik
Neměnnost explicitní string, další přes rozhraní
Práce s pamětí vlastnictví GC
Detekce souběhu ano jen nepřímo
Závislosti cargo Go moduly
error[E0382]: use of moved value: `c`
--> an_example.rs:40:8
|
39 | funkce1(c);
| - value moved here
40 | funkce2(c);
| ^ value used here after move
|
= note: move occurs because `c` has type `std::rc::Rc<Complex>`, which does not implement the `Copy` trait
fn foo(a int32) {
println!(a)
}
fn main() {
let x:i32 = 10
foo(x);
}
i8
, u128
atd.// odvození typu všech proměnných (i z)
// použití makra println!
fn main() {
let x = 6;
let y = 7;
let z;
// překladač až nyní získá informace o typu
z = x * y;
println!("{} * {} = {}", x, y, z);
}
Option
null
fn div(x: i32, y: i32) -> Option<i32> {
if y != 0 {
Some(x / y)
} else {
None
}
}
fn main() {
let z1 = div(2, 1);
println!("{:?}", z1);
let z2 = div(2, 0);
println!("{:?}", z2);
}
Result
null
popř. speciálních chybových hodnotfn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn main() {
let z1 = div(2, 1);
println!("{:?}", z1);
let z2 = div(2, 0);
println!("{:?}", z2);
}
Result
a pattern matchingfn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn print_div_result(result: Result<i32, &'static str>) {
match result {
Ok(value) => println!("value: {}", value),
Err(error) => println!("error: {}", error),
}
}
fn main() {
let z1 = div(2, 1);
print_div_result(z1);
let z2 = div(2, 0);
print_div_result(z2);
}
Result
při výpočtechfn div(x: i32, y: i32) -> Result<i32, &'static str> {
if y != 0 {
Ok(x / y)
} else {
Err("Divide by zero!")
}
}
fn print_div_result(result: Result<i32, &'static str>) {
match result {
Ok(value) => println!("value: {}", value),
Err(error) => println!("error: {}", error),
}
}
fn inc(x: i32) -> i32 {
x + 1
}
fn main() {
let z0 = div(0, 1);
print_div_result(z0);
print_div_result(z0.map(inc));
let z2 = div(2, 0);
print_div_result(z2);
print_div_result(z2.map(inc));
}
fn main() {
let is_odd = |x: i32| x & 1 == 1;
//let is_even = |x: i32| !is_odd(x);
let square = |x: i32| x*x;
for x in 0..10 {
println!("{}*{}={}, {} is {} number",
x, x, square(x), x, if is_odd(x) {"odd"} else {"even"})
}
}
fn main() {
let is_odd = |x: i32| x & 1 == 1;
//let is_even = |x: i32| !is_odd(x);
let square = |x: i32| x*x;
for x in 0..10 {
println!("{}*{}={}, {} is {} number",
x, x, square(x), x, if is_odd(x) {"odd"} else {"even"})
}
}
mut
range
)map
filter
take
take_while
fold
fn main() {
for n in 1..10 {
let fact = (1..n + 1).fold(1, |prod, x| prod * x);
println!("{}! = {}", n, fact);
}
}
fn main() {
let iter1 = 1..;
let iter2 = iter1.filter(|x| x % 2 == 0);
let iter3 = iter2.take(10);
let suma = iter3.fold(0, |sum, x| sum + x);
println!("sum = {}", suma);
}
// matching (nejjednodušší varianta)
fn main() {
let x: i32 = 1;
match x {
0 => println!("zero"),
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("something else"),
}
}
// matching, složitější ukázka
fn classify(x:i32) -> &'static str {
match x {
0 => "zero",
1 | 2 => "one or two",
3 | 4 | 5 => "from three to five",
10 ... 20 => "from ten to twenty",
_ => "something else",
}
}
fn main() {
for x in 0..10 {
println!("{}:{}", x, classify(x))
}
}
NULL
/nil
fn main() {
let x = Box::new(42);
println!("{}", x);
}
let c = Box::new(Complex::new(1.0, 2.0));
// deref
fn print_complex(c: Box<Complex>) {
println!("Complex number: {:}+{:}i", c.real, c.imag);
}
Rc::clone()
Deref
trait)fn main() {
println!("main begin");
let c = Rc::new(Complex::new(0.0, 0.0));
c.print();
{
println!("inner block begin");
let c2 = Rc::new(Complex::new(0.0, 0.0));
c2.print();
{
println!("inmost block begin");
let c3 = Rc::new(Complex::new(0.0, 0.0));
c3.print();
println!("inmost block end");
}
println!("inner block end");
}
println!("main end");
}
// jeden sdílený objekt referencovaný třikrát
fn main() {
println!("main begin");
let c = Rc::new(Complex::new(0.0, 0.0));
c.print();
{
println!("inner block begin");
let c2 = c.clone();
c2.print();
{
println!("inmost block begin");
let c3 = c.clone();
c3.print();
println!("inmost block end");
}
println!("inner block end");
}
println!("main end");
}
Arc::clone()
Deref
traitfn start_threads() {
let c = Arc::new(Complex::new(1.0, 1.0));
for id in 0..10 {
let owner = ComplexNumberOwner { id: id, value: c.clone() };
// move protože objekt může přežít toto vlákno
thread::spawn(move || {
owner.print();
delay(400);
});
}
}
fn main() {
let array = [10, 20, 30, 40];
// délka pole
println!("array has {} items", array.len());
// range + délka pole
for i in 0..array.len() {
println!("item #{} = {}", i + 1, array[i]);
}
// for-each
for i in array.iter() {
println!("{}", i);
}
}
fn main() {
let array = [1; 10];
// délka pole
println!("array has {} items", array.len());
// range + délka pole
for i in 0..array.len() {
println!("item #{} = {}", i + 1, array[i]);
}
// for-each
for i in array.iter() {
println!("{}", i);
}
}
fn main() {
let vector = vec![1, 2, 3, 4, 5];
// délka vektoru
println!("vector has {} items", vector.len());
// range + délka pole
for i in 0..vector.len() {
println!("item #{} = {}", i + 1, vector[i]);
}
// for-each
for item in vector.iter() {
println!("{}", item);
}
// také funguje
for item in &vector {
println!("{}", item);
}
}
fn main() {
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let array2 = &array[2..6];
for i in array2.iter() {
println!("{}", i);
}
}
fn main() {
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let array2 = &array[5..];
for i in array2.iter() {
println!("{}", i);
}
}
fn main() {
let vector = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
println!("vector has {} items", vector.len());
let slice = &vector[3..7];
println!("slice has {} items", slice.len());
}
use std::thread;
fn main() {
println!("Starting");
for i in 1..10 {
thread::spawn(move || {
println!("Hello from a thread #{}", i);
});
}
println!("Stopping");
}
cargo test
#[test]
fn ok_test() {
}
#[test]
fn failure() {
assert!(false);
}
mockiato
- mockingmockito
- HTTP mockingrust-fuzz/afl.rs
- fuzzer postavený nad AFLCargo.toml
[package]
name = "projectXYZ"
version = "0.1.0"
authors = ["Pepa z depa <pepa@openalt.cz>"]
[dependencies]
rand = "0.3.14"
$ cargo build
Compiling project1 v0.1.0 (file:///home/tester/temp/project1)
Finished debug [unoptimized + debuginfo] target(s) in 0.37 secs
$ cargo build
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
$ cargo run
Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/project1`
Hello, world!
$ cargo test
Compiling project1 v0.1.0 (file:///home/tester/temp/project1)
Finished debug [unoptimized + debuginfo] target(s) in 0.43 secs
Running target/debug/project1-b888664ab405e319
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
$ cargo install
Compiling libc v0.2.17
Compiling rand v0.3.14
Compiling projectXYZ v0.1.0 (file:///home/tester/temp/projectXYZ)
Finished release [optimized] target(s) in 5.88 secs
Installing /home/tester/.cargo/bin/projectXYZ
warning: be sure to add `/home/tester/.cargo/bin` to your PATH to be able to run the installed binaries
mysql-proxy-rs
rust-postgres
redis-rs
mongo-rust-driver
diesel
ndarray
cargo-web
hyper
(HTTP client)Gotham
(web framework)tiny-http
Iron
(založeno na konceptu middleware)
futures-jsonrpc
nanomsg-rs
stomp-rs
rust-zmq
ctypes
nebo CFFI
#[no_mangle]
pub extern fn add_integers(x: i32, y: i32) -> i32 {
x + y
}
#!/usr/bin/env python3
import ctypes
testlib1 = ctypes.CDLL("target/debug/libtest1.so")
result = testlib1.add_integers(1, 2)
print("1 + 2 = {}".format(result))
result = testlib1.add_integers(1.5, 2)
print("1.5 + 2 = {}".format(result))