3

【Rust5】基础包

 2 years ago
source link: https://www.guofei.site/2022/09/13/rust5.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

rand随机

rand = "0.8.3"

use rand::Rng;


// 每个线程都有一个初始化的生成器
let mut rng = rand::thread_rng();

// 整数范围是该类型的范围
let n1: u8 = rng.gen();
let n2: u16 = rng.gen();
// 浮点数的范围是0到1,但不包括1
let f1: f64 = rng.gen();

生成一个范围内的随机数

let f2_rnd: f64 = rng.gen_range(0.0..10.0);
let i2_rnd: i32 = rng.gen_range(0..10);
// 整数
Uniform::from(1..7);
// 浮点数
Uniform::from(1.0..7.0);


// 更复杂的类型用 rand_distr
use rand_distr::{Normal, Binomial, Gamma};

// mean 2, standard deviation 3
let mut normal = Normal::new(2.0, 3.0).unwrap();
let val = normal.sample(&mut rand::thread_rng());

案例:随机生成密码

use rand::Rng;
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
                        abcdefghijklmnopqrstuvwxyz\
                        0123456789)(*&^%$#@!~";
const PASSWORD_LEN: usize = 30;
let mut rng = rand::thread_rng();

let password: String = (0..PASSWORD_LEN)
    .map(|_| {
        let idx = rng.gen_range(0..CHARSET.len());
        CHARSET[idx] as char
    })
    .collect();

sort

vec.sort 可以用于 int, &str 但不能用于 float

let mut vec = vec![1, 5, 10, 2, 15];
let mut vec = vec!["aa", "ab", "b"];

vec.sort();
print!("{:?}", vec);

下面这种写法很通用

let mut vec = vec![1.1, 1.15, 5.5, 1.123, 2.0];
vec.sort_by(|a, b| a.partial_cmp(b).unwrap());

案例:对 vec<struct> 排序

struct Person {
    name: String,
    age: u32,
}

impl Person {
    fn new(name: String, age: u32) -> Self {
        Person { name, age }
    }
}

fn main() {
    let mut people = vec![
        Person::new("Zoe".to_string(), 25),
        Person::new("Al".to_string(), 60),
        Person::new("John".to_string(), 1),
    ];

    people.sort_by(|a, b| b.age.cmp(&a.age));
}

命令行

// clap = "*"
use clap::{Arg, App};

fn main() {
    let matches = App::new("app名称")
        .version("0.0.1")
        .author("guofei9987 <[email protected]>")
        .about("关于,这个app是干什么的")
        .arg(Arg::with_name("file")
            .short('f')
            .long("file")
            .takes_value(true)
            .help("A cool file"))
        .arg(Arg::with_name("num")
            .short('n')
            .long("number")
            .takes_value(true)
            .help("Five less than your favorite number"))
        .get_matches();

    let myfile = matches.value_of("file").unwrap_or("input.txt");
    println!("The file passed is: {}", myfile);

    let num_str = matches.value_of("num");
    match num_str {
        None => println!("No idea what your favorite number is."),
        Some(s) => {
            match s.parse::<i32>() {
                Ok(n) => println!("Your favorite number must be {}.", n + 5),
                Err(_) => println!("That's not a number! {}", s),
            }
        }
    }
}
# 正经使用
cargo run -- -f myfile.txt -n 251

# -V 和 --version 显示app名称+版本
cargo run -- -V

# -h, --help 显示详细的帮助信息
cargo run -- -h

ANSI:彩色命令行

// ansi_term = "*"
use ansi_term::Colour;
use ansi_term::Style;

fn main() {
    println!("This is {}, {}, {} and {}. This is {}.",
             Colour::Red.paint("red"),
             Colour::Blue.paint("blue"),
             Colour::Green.paint("green"),
             Colour::Yellow.paint("yellow"),
             Style::new().bold().paint("bold"),
    );
}

time

let start = Instant::now();
thread::sleep(Duration::from_secs(1));
let duration = start.elapsed();
// duration 可以转化为很多种数字格式
// duration.as_secs_f32(); // 返回 f32,
// std::time::Duration 重复了,所以做个别名
use chrono::Duration as Duration2;

let now = Utc::now();
now.checked_add_signed(Duration2::days(-1))
// 还可以用checked_sub_signed
// Duration2:: 可以是:
// days, weeks,
// hours, minutes, milliseconds, microseconds

时区(略)

生成时间对象

let now = Utc::now();

let date_time = chrono::NaiveDate::from_ymd(2017, 11, 12).and_hms(17, 33, 44);

时间对象格式转字符串

let now = Utc::now();

// 标准格式时间
let time_str = format!("{}-{:02}-{:02} {:02}:{:02}:{:02}",
                       now.year(), now.month(), now.day(),
                       now.hour(), now.minute(), now.second());



// 其它格式时间
let (is_common_era, year) = now.year_ce();
println!(
   "The current UTC date is {}-{:02}-{:02} {:?} ({})",
   year,
   now.month(),
   now.day(),
   now.weekday(),
   if is_common_era { "CE" } else { "BCE" }
);

let (is_pm, hour) = now.hour12();
println!(
   "The current UTC time is {:02}:{:02}:{:02} {}",
   hour,
   now.minute(),
   now.second(),
   if is_pm { "PM" } else { "AM" }
);

时间对象转 timestamp

now.timestamp()

字符串转日期

let no_timezone = chrono::NaiveDateTime::parse_from_str("2015-09-05 23:56:04", "%Y-%m-%d %H:%M:%S")
    .unwrap();

正则

[dependencies]
regex = "*"
// 编译正则
let re = Regex::new("\\b[\\w\\-\\+\\.]+@[\\w\\-\\+\\.]+\\.\\w{2,18}\\b").unwrap();
let text = "aaa  [email protected] [email protected]";


// 是否有匹配,
let res: bool = re.is_match(text);
// true


// 单匹配
let mut res = Vec::new();
match re.captures(text) {
  // 这里面的序号0代表整体,序号1代表分组1
    Some(i) => { res.push(String::from(&i[0])) }
    None => {}
}




// 多匹配
let mut res = Vec::new();
for cap in re.captures_iter(text) {
    res.push(String::from(&cap[0]));
}


// 匹配并替换
let text_new = re.replace_all(text, "你");

关于分组运算

// 编译正则,定义老公两个组,分别命名为 user_name 和 domain
let re = Regex::new("\\b(?P<name>[\\w\\-\\+\\.]+)@[\\w\\-\\+\\.]+\\.(?P<domain>\\w{2,18})\\b").unwrap();
let text = "aaa  [email protected] [email protected]";
let text2 = "aaaaaaa";


// 单匹配:上面用 index 方便一些,如果想用name:
// re.captures(text) 是一个 `<Option<Captures<"user_name":Option>>>` 这种嵌套
let mut res: Vec<String> = Vec::new();
match re.captures(text) {
    Some(i) => {
        res.push(String::from(i.name("user_name").unwrap().as_str()));
    }
    None => {}
}

// 还可以这样,但是匹配不到的时候直接 Panic 了
let res: &str = cap.unwrap().name("user_name").unwrap().as_str();


// 多匹配
let mut res = Vec::new();
for cap in re.captures_iter(&text) {
    match cap.name("user_name") {
        None => {}
        Some(i) => { res.push(String::from(i.as_str())) }
    }
}


// 替换
let text_new = re.replace_all(text, "$user_name/$domain");

参考:https://blog.csdn.net/wsp_1138886114/article/details/116519242 (rust的正则和python的正则有些区别,功能更多)

字符串临时

用的pcre

fn get_mod_match(&self, text: &str) -> Vec<String> {
    let text = text.as_bytes();
    let mut res = Vec::new();
    for re in &self.re_set {
        for cap in re.captures_iter(text) {
            match cap {
                Ok(cap) => res.push(String::from_utf8_lossy(cap.index(0)).parse().unwrap()),
                Error => {}
            }
        }
    }
    return res;
}
let my_str_u: &[u8] = b"hello";

let my_str: &str = "hello";


// 互相转换
let new_my_str_u: &[u8] = my_str.as_bytes();

String::from_utf8_lossy(my_str_u);
String::from(my_str);


<String>.as_str()
<String>.as_bytes()

测试性能

[dependencies]

bench = "*"

lib.rs

#![feature(test)]
pub mod benchmarks;

benchmarks.rs

#![feature(test)]
extern crate test;

use test::Bencher;


#[bench]
fn bench_pcre2_is_match(b: &mut Bencher) {
    let pcre_re: pcre2::bytes::Regex = pcre2::bytes::Regex::new(r#"he.{0,2}o"#).unwrap();
    b.iter(|| pcre2_is_match(&pcre_re));
}

额外


// 如何匹配 Option
match opt {
  Some(i)=>{},
  None=>{}
}

// 如何匹配 Result
match res {
  Ok{t}=>{}
  Err(e)=>{}
}

改一个数字

fn myfun(a: &mut i32){
    *a+=1;
}
fn main() {
    let mut a=1;
    myfun(&mut a);
    println!("{}",a); // 为 2
}

tar(待补充)

https://rust-lang-nursery.github.io/rust-cookbook/compression/tar.html

密码学(待补充)

https://rust-lang-nursery.github.io/rust-cookbook/cryptography/encryption.html

ring::pbkdf2

SQLite 和 Postgres(待补充)

https://rust-lang-nursery.github.io/rust-cookbook/database/sqlite.html

如何打log(待补充)

https://rust-lang-nursery.github.io/rust-cookbook/development_tools.html

参考资料

https://llever.com/rust-cookbook-zh/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK