============
== vtranq ==
============

Rust Tips

Installation

curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
rustc --version

Prepare data

wget https://ftp.ncbi.nlm.nih.gov/pub/clinvar/tab_delimited/variant_summary.txt.gz
gunzip variant_summary.txt.gz

Hello world

  • Tạo hello.rs
fn main() {
    println!("Hello");
}
  • Compile
rustc hello.rs
  • Run
./hello

Hello world with Cargo

  • Tạo project
cargo new hello
cd hello
  • Edit /src/main.rs
fn main() {
    println!("Hello");
}
  • Compile
cargo build
  • Run
cargo run

Tối ưu hóa khi chạy

cargo run --release

Working with MySQL

use mysql::*;
use mysql::prelude::*;
use chrono::prelude::*; //For date and time

fn main() {
    let opts = OptsBuilder::new()
        .ip_or_hostname(Some("127.0.0.1"))
        .user(Some("username"))
        .pass(Some("password"))
        .db_name(Some("database"));

    let pool = Pool::new(opts).unwrap();

    let mut conn = pool.get_conn().unwrap();
}

Query

    conn.query_iter("select TITLE, MIM_NUMBER from CLINICAL_SYNOPSIS LIMIT 0, 10")
    .unwrap()
    .for_each(|row| {
        let r:(String, String) = from_row(row.unwrap());
        println!("{:?}, {:?}", r.0, r.1);
    });

Insert

pub struct Clinvar {
    pub VARIANT: String,
    pub CLINICAL: String,
    pub PHENOTYPE: String
}

fn main() {

    ...

    let clinvar = Clinvar {
        VARIANT: String::from("NM_139007.3(HFE):c.77-273G>C"),
        CLINICAL: String::from("Pathogenic"),
        PHENOTYPE: String::from("xxx")
    };

    match insert_clinvar(&mut conn, &clinvar) {
        Ok(last_id) => println!("Inserted product with ID {}", last_id),
        Err(e) => println!("Error: {:?}", e),
    }
}

fn insert_clinvar(
    conn: &mut PooledConn,
    clinvar: &Clinvar) -> std::result::Result<u64, mysql::error::Error> {

    let uuid = ::uuid::Uuid::new_v4();

    conn.exec_drop(
        "insert into CLINVAR (VARIANT, CLINICAL, PHENOTYPE, GUID, UDID, UUID) values (:variant, :clinical, :phenotype, 1, 1, :uuid)",
        params! {
            "variant" => &clinvar.VARIANT,
            "clinical" => &clinvar.CLINICAL,
            "phenotype" => &clinvar.PHENOTYPE,
            "uuid" => uuid.simple().to_string()
        },
    )
    .and_then(|_| Ok(conn.last_insert_id()))
}

UUID

Thêm vào trong Cargo.toml ở mục dependencies như sau:

[dependencies]
uuid = { version = "0.6", features = ["serde", "v4"] }

Trong code, tạo UUID như sau:

let uuid = ::uuid::Uuid::new_v4();
let uuid_string = uuid.simple().to_string();
let uuid_string_2 = uuid.hyphenated().to_string();

Ellapsed time

REF: https://rust-lang-nursery.github.io/rust-cookbook/datetime/duration.html

use std::time::{Duration, Instant};

fn main() {
    let start = Instant::now();
    expensive_function();
    let duration = start.elapsed();

    println!("Time elapsed in expensive_function() is: {:?}", duration);
}

String replacement using regex

Add to Cargo.toml

[dependencies]
lazy_static = "*"
regex = "*"

Sample code:

use lazy_static::lazy_static;
use regex::Regex;
use std::borrow::Cow;

fn ensure_variant_name(name: &str) -> Cow<str> {
    lazy_static! {
        static ref NAME_REGEX : Regex = Regex::new(
            r"(?P<p1>[^\(]+)\([A-Z0-9]+\)(?P<p2>[^\(]+)\(?.*"
            ).unwrap();
    }
    NAME_REGEX.replace_all(name, "$p1$p2")
}

Chạy code xử lý genome

cp9
cd dev/rust/hello/
cargo run --release

Curl & proxy

HTTP client

  • If you want a low-level HTTP library in Rust, I recommend using hyper. It’s production-ready and fully written in Rust so you don’t have to worry too much about safety issues. Moreover, it’s the only library that mentions production-readiness.
  • For a more high-level HTTP library, I would go with reqwest. The library is built on top of hyper, so it offers many of the same advantages as hyper and has a more convenient syntax to boot.

Rust & blockchain

Rust & bitcoin

Scraper

  • Dùng thư viện https://crates.io/crates/scraper
  • Scrapping is io bound so I wouldn’t bother choosing the language with performance as the criterion. Instead, I focus more on what the frameworks provide and ease of coding.

Count by lines

// We want to use the lines method from this trait
use std::io::BufRead;

// Let's us use ? for simple error handling
fn main() -> Result<(), std::io::Error> {
    // Try to open the file
    let file = std::fs::File::open("input.txt")?;
    // Create a buffered version of the file so we can use lines
    let buffered = std::io::BufReader::new(file);

    // Iterate through each line in the file
    for line in buffered.lines() {
        // But we get a Result each time, get rid of the errors
        let line = line?;
        // And print out the line length and content
        println!("{} {}", line.len(), line);
    }

    // Everything went fine, so we return Ok
    Ok(())
}

Web server

  • Nên dùng actix-web cho web API
use actix_web::{web, App, HttpRequest, HttpServer, Responder};

async fn greet(req: HttpRequest) -> impl Responder {
    let name = req.match_info().get("name").unwrap_or("World");
    format!("Hello {}!", &name)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(greet))
            .route("/{name}", web::get().to(greet))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

References