Skip to content

Latest commit

 

History

History
528 lines (415 loc) · 21.4 KB

rust.md

File metadata and controls

528 lines (415 loc) · 21.4 KB

Rust

Video tutorials

Blogs

Books

GUI

CLI

Traits

&dyn Trait
&Trait
Box<Trait>
Box<dyn Trait>

Crates

Concurrency and parallelism

Testing

Test response status

assert_eq!(res.status(), 200);

Container images

Auto recompile

Kubernetes

HTTP server

HTTP Client

Tools

Performance

Trait bounds

fn notify(item: impl Summary) -> String {}

fn notify<T: Summary>(item: T) -> String {}

fn notify<T> Summary(item: T) -> String
    where T: Summary {}

Macros

matches!

fn is_first(data: Test) -> bool {
    match data {
            Test::FIRST => true,
            _ => false,
        }
}
fn is_first(data: Test) -> bool {
    matches!(data, Test::FIRST)
}

unimplemented!

When a function is not implemented, use unimplemented! macro inside the body.

Useful if you are prototyping and are just looking to have your code typecheck.

Error handling

#[derive(Fail)]
pub enum MyError {
    Server(u8)
    User(String)
    Connection,
}

Mutex poison to custom error conversion

#[derive(Debug)]
enum MyError {
    Lock,
}

impl<T> From<PoisonError<T>> for MyError {
    fn from(_: PoisonError<T>) -> MyError {
        MyError::Lock
    }
}

fn main() -> Result<(), MyError> {}

Do not unwind stack on panic

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

Match error kind

let f = match File::open("file.txt") {
    Ok(file) => do_something_with(file),
    Err(e) => match e.kind() {
        ErrorKind::NotFound => match File::create("file.txt") {
            Ok(file2) => do_something_with(file2),
            Err(e2) => panic!("{:?}", e2)
        },
        _ => panic!("something weird happened")
    }
}

Return errors in functions

fn read_file() => Result<String, io::Error> {
    let mut f = File::open("file.txt") {
        Ok(file) => do_something_with(file),
        Err(e) => return Err(e), // here we need return
    }

    let mut s = String::new();
    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),   // return not needed here because match is the last expression in the function
        Err(e) => Err(e), // return not needed here because match is the last expression in the function
    }
}

Short way to return errors in functions

fn read_file() => Result<String, io::Error> {
    let mut f = File::open("file.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}
fn read_file() => Result<String, io::Error> {
    let mut s = String::new();
    File::open("file.txt")?.read_to_string(&mut s)?;
    Ok(s)
}

Return error in main()

fn main() => Result<(), Box<dyn Error>> {
    let f File::open("file.txt")?;
    Ok(s)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {}
use thiserror::Error;

#[derive(Error, Debug)]
pub enum DataStoreError {
    #[error("data store disconnected")]
    Disconnect(#[from] io::Error),
    #[error("the data for key `{0}` is not available")]
    Redaction(String),
    #[error("invalid header (expected {expected:?}, found {found:?})")]
    InvalidHeader {
        expected: String,
        found: String,
    },
    #[error("unknown data store error")]
    Unknown,
}

Iterators

Iterator over struct fields

use std::iter::once;

struct Color {
    r: u8,
    g: u8,
    b: u8,
}

impl Color {
    fn iter(&self) -> impl Iterator<Item = u8> {
        once(self.r).chain(once(self.g)).chain(once(self.b))
    }
}

fn main() {
    let color = Color {
        r: 100,
        g: 0,
        b: 150,
    };
    for v in color.iter() {
        println!("{}", v);
    }
}

Cast to std::any::Any

Box::new(Foo { data: 32 }) as Box<dyn Any>

View create documentation skipping dependencies

cargo doc --no-deps --open

Stricter compiler lints

#![warn(missing_debug_implementations, rust_2018_idioms, missing_docs)]

List all compiler lints

rustc -W help

Update Rust toolchain

rustup update stable

use can be used inside functions

fn print_power_action(state: PowerState) {
    use PowerState::*;
    match state {
        Off,
        Sleep,
        Reboot,
        Shutdown,
        Hibernate,
    }
}

let ref mut remainder = self.remainder?; // self.remainder: Option<&str>

is equal to

let remainder = self.remainder.as_must()?;

PostgreSQL mTLS connection

extern crate openssl;
extern crate postgres;

use postgres::{Connection, TlsMode};

use openssl::ssl::{SslConnectorBuilder, SslMethod, SslVerifyMode};
use openssl::x509;

fn main() {
    let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
    connector.set_ca_file("root.crt").unwrap();
    connector
        .set_certificate_file("postgresql.crt", x509::X509_FILETYPE_PEM)
        .unwrap();

    connector
        .set_private_key_file("postgresql.key", x509::X509_FILETYPE_PEM)
        .unwrap();

    // openssl::ssl::SslVerfifyMode constant in not defined yet in openssl 0.9.23 which is rust-postgres dependency
    // disable certificate hostname check
    let mode = SslVerifyMode::empty();
    connector.set_verify(mode);

    let negotiator = postgres::tls::openssl::OpenSsl::from(connector.build());

    let conn = Connection::connect(
        "postgres://postgres@localhost:5432",
        TlsMode::Require(&negotiator),
    ).unwrap();
    let res = conn.query("SELECT 1+1 as foo", &[]).unwrap();
    for row in &res {
        let foo: i32 = row.get(0);
        println!("{}", foo);
    }
}

SixtyFPS

apt-get install cmake libfontconfig1-dev libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev

Dependencies

git dependency

[dependencies]
winit = { git = "https://github.com/project/crate", branch = "branch-name" }

Overriding dependency

[patch.crates-io]
winit = { git = "https://github.com/project/crate", branch = "branch-name" }