## 入门

### 配置 vscode 调试

配置参考。下载 CodeLLDB，选择 rust 自动生成 launch.json 文件

    {
      "configurations": [
        // 添加一下行，使 vec/hashmap 等类型显示正常
        "sourceLanguages": ["rust"]
      ]
    }

将编译文件与标准库的位置进行映射

    {
      "lldb.launch.sourceMap": {
        // 你自己的映射 hash 和映射路径
        "/rustc/4b91a6ea7258a947e59c6522cd5898e7c0a6a88f": "/Users/feiwu/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust"
      }
    }

### Hello_World.rs

    fn main() {
      println!("Hello, World!");
    }

#### 编译运行

    $ rustc Hello_World.rs
    $ ./Hello_World

    Hello, World!

### 原始类型

:- | :-
--- | ---
`bool` | 布尔值 (`true` / `false`)
`char` | 字符
`f32`, `f64` | 32 位、64 位浮点数
`i64`, `i32`, `i16`, `i8` | 有符号 16- ... 整数
`u64`, `u32`, `u16`, `u8` | 无符号 16 位，... 整数
`isize` | 指针大小的有符号整数
`usize` | 指针大小的无符号整数

查看: Rust 类型

### 格式化

    // 单个占位符
    println!("{}", 1);
    // 多个占位符
    println!("{} {}", 1, 3);
    // 位置参数
    println!("{0} 是 {1} {2}，{0} 也是 {3} 编程语言", "Rust", "cool", "language", "safe");
    // 命名参数
    println!("{country} 是一个团结的国家", country = "China");
    // 占位符特征 :b 表示二进制， :0x 表示十六进制， :o 表示八进制
    println!("让我们打印 76 是二进制的 {:b} ，十六进制等价物是 {:0x} 八进制等价物是 {:o}", 76, 76, 76);
    // 调试特征
    println!("使用调试特征 {:?} 在此处打印我们想要的任何内容", (76, 'A', 90));

    // 1.58 中的新格式字符串
    let x = "world";
    println!("Hello {x}!");

### 打印风格

    // 打印输出
    print!("Hello World\n");
    // 打印后追加新行
    println!("追加新行");
    // 打印为错误
    eprint!("这是一个错误\n");
    // 打印为新行错误
    eprintln!("这是新行的错误");

### 变量

    // 初始化和声明变量
    let some_variable = "This_is_a_variable";
    // 使变量可变
    let mut mutable_variable = "Mutable";
    // 分配多个变量
    let (name, age) = ("ElementalX", 20);
    // （全局）常量
    const SCREAMING_SNAKE_CASE:i64 = 9;

### 注释

    // 行注释
    /*.............块注释 */
    /// 外部文档注释
    //! 内部文档评论

另见: 注释 (doc.rust-lang.org)

### 函数

    fn test(){
      println!("这是一个函数!");
    }
    fn main(){
      test();
    }

查看: Functions

### 声明宏

    macro_rules! foo {
      ($l:tt) => { bar!($l); }
    }
    macro_rules! bar {
      (3) => {}
    }
    foo!(3);

### 元变量

:- | :-
--- | ---
`item` | 程序项
`block` | 块表达式
`stmt` | 语句 (注意此选择器不匹配句尾的分号)
`pat` | 模式
`expr` | 表达式
`ty` | 类型
`ident` | 标识符或关键字
`path` | 类型表达式 形式的路径
`tt` | `token` 树 (单个 `token` 或宏匹配定界符 `()`、`[]` 或 `{}` 中的标记)
`meta` | 属性，属性中的内容
`lifetime` | 生存期 `token`
`vis` | 可能为空的可见性限定符
`literal` | 匹配 `-?` 字面量表达式

### 结构体

结构体是一个使用关键字 `struct` 定义的标称型(nominal)结构体类型

    struct Point { x: i32, y: i32 }
    let p = Point { x: 10, y: 11 };
    let px: i32 = p.x;

#### 元祖结构体

    struct Color (i32, i32, i32);
    let black = Color(0,0,0);

#### 单元结构体

不关心该类型的内容, 只关心它的行为。

    struct Solution;
    impl Solution{
        // ...
    }

### 语句与表达式

在 rust 中，语句无需返回值，而表达式总要返回值

#### 语句

    let a = "hello".to_string();
    let b = a + " world";
    println!("{}", b);

#### 表达式

    fn main(){
        let x = {
            let a = "hello".to_string();
            a + " world"
        };
        println!("{}", x);
        // hello world
    }

## Rust 类型

### 类型别名

    type Point = (u8, u8);
    let p: Point = (41, 68);

### 整数

    let mut a: u32 = 8;
    let b = 877_u64;
    let c = 8999i64;
    let d = -90;

### 浮点数

    let mut sixty_bit_float: f64 = 89.90;
    let thirty_two_bit_float: f32 = 7.90;
    let just_a_float = 69.69;

### 布尔值

    let true_val: bool = true;
    let false_val: bool = false;
    let just_a_bool = true;
    let is_true = 8 < 5;  // => false

### 字符

    let first_letter_of_alphabet = 'a';
    let explicit_char: char = 'F';
    let implicit_char = '8';
    let emoji = "\u{1f600}";   // => 😀

### 字符串字面量

    let community_name = "AXIAL";
    let no_of_members: &str = "ten";
    println!("社区的名称是 {community_name}，它有 {no_of_members} 个成员");

查看: 字符串

### 数组

这里介绍的是固定长度的数组。rust 中常用的是集合类型 vec 表示的动态数组

    ┌─────┬─────┬─────┬─────┬─────┬─────┐
    | 92  | 97  | 98  | 99  | 98  | 94  |
    └─────┴─────┴─────┴─────┴─────┴─────┘
       0     1     2     3     4     5

    let array: [i64; 6] = [92,97,98,99,98,94];

    let mut array: [i32 ; 3] = [2,6,10];
    array[1] = 4;
    array[2] = 6;

使用 `mut` 关键字使其可变

### 切片

    let mut array: [ i64; 4] = [1,2,3,4];
    // 下限包括在内，上限不包括在内
    let mut slices: &[i64] = &array[0..3]
    println!("切片的元素是：{slices:?}");

### 元组

    let tuple = (1, 'A' , "Cool", 78, true);

## Rust 字符串

### 字符串字面量

    let cs:&str = "备忘清单";
    // => 为开发者分享备忘单
    println!("为开发者分享 {cs}");

### 字符串对象

    // 创建一个空字符串对象
    let my_string = String::new;
    // 转换为字符串对象
    let S_string = a_string.to_string()
    // 创建一个初始化的字符串对象
    let lang = String::from("Rust");
    println!("First language is {lang}");

### .capacity()

    let rand = String::from("Random String");
    rand.capacity()  // => 13

以字节为单位计算字符串的容量

### .contains()

    let name = String::from("ElementalX");
    name.contains("Element") // => true

检查子字符串是否包含在原始字符串中

### 添加单个字符

    let mut half_text = String::from("Hal");
    half_text.push('f');    // => Half

### 添加整个字符串

    let mut hi = String::from("Hey there...");
    hi.push_str("How are you doing??");
    // => Hey there...How are you doing??
    println!("{hi}");

### 原生字符串

    let str1 = r#"\hello"#;
    println!("{}", str1);
    // \hello

原生字符串，无需增加转义字符（`\`）转义

### 字节和字节串

    let str2 = b'a';
    println!("{}", str2);
    // 97
    let str3 = b"\\hello";
    println!("{:?}", str3);
    // [92, 104, 101, 108, 108, 111]
    let str4 = br#"\hello"#;
    println!("{:?}", str4);
    // [92, 104, 101, 108, 108, 111]

## Rust 动态数组

### 创建动态数组

    let v: Vec<i32> = Vec::new();
    // 使用宏
    let v1 = vec![1, 2, 3];

### 读取元素

    let v = vec![1, 2, 3, 4, 5];

    let element = &v[100];
    // panic，越界
    let element2 = v.get(100);
    println!("{:?}", element2);
    //None

### 遍历数组

1. 只读取数组中的元素

       let v = vec![1, 2, 3];
       for i in &v {
           println!("{}", i);
       }

2. 遍历的同时修改数组中的元素

       let mut v = vec![1, 2, 3];
       for i in &mut v {
           *i += 10
       }

### 多维数组

         j0   j1   j2   j3   j4   j5
       ┌────┬────┬────┬────┬────┬────┐
    i0 | 1  | 2  | 3  | 4  | 5  | 6  |
       ├────┼────┼────┼────┼────┼────┤
    i1 | 6  | 5  | 4  | 3  | 2  | 1  |
       └────┴────┴────┴────┴────┴────┘

    let arr = vec![
        vec![1, 2, 3, 4, 5, 6],
        vec![6, 5, 4, 3, 2, 1]
    ];

### 常用方法

- | :-
--- | ---
`len()` | 返回 `vec` 的长度
`is_empty()` | `vec` 是否为空
`push(value)` | 在 `vec` 尾部插入元素
`pop()` | 删除并返回 `vec` 尾部的元素或者返回 `None`
`insert(index,element)` | 在指定索引处插入元素
`remove(index)` | 删除指定索引处的元素并返回被删除的元素，索引越界将 panic 报错退出
`clear()` | 清空 `vec`
`append(vec)` | 将另一个 `vec` 中的所有元素追加移入 `vec` 中，移动的 `vec` 变为空
`truncate(len)` | 将 `vec` 截断到指定长度,多余的元素被删除
`retain(f)` | 根据给定的函数，保留满足条件的元素
`drain(range)` | 删除 `vec` 中指定范围的元素,同时返回一个迭代该范围所有元素的迭代器
`split_off(index)` | 切分 `vec`，索引左边的元素保留在原 `vec` 中(含索引)，索引右边的元素(不含索引)在返回的 `vec` 中

## 枚举

### 在结构体中使用枚举

    enum IpAddrKind {
      V4,
      V6,
    }
    struct IpAddr {
      kind: IpAddrKind,
      address: String,
    }

    fn main(){
        let ip = IpAddr{
            kind: IpAddrKind::V4,
            address: String::from("127.0.0.1")
        };
    }

### 枚举的变体

    enum IpAddrKind {
      V4(u8, u8, u8, u8),
      V6(String),
    }

    fn main() {
      let home = IpAddrKind::V4(127, 0, 0, 1);
      let loopback = IpAddrKind::V6(String::from("::1"));
    }

    enum Message{
      Quit,
      Move {x:i32, y:i32},
      Write(String),
      ChangeColor(i32, i32, i32),
    }
    fn main(){
      let q = Message::Quit;
      let m = Message::Move {x:10, y:20};
      let w = Message:: Write(String::from("hello"));
      let c = Message::ChangeColor(10, 20, 30);
    }

### 模式匹配结构体

    #[derive(Debug)]
    enum Grade {
        A,
        B,
        C,
    }
    enum Subject {
        Math(Grade),
        English(Grade),
    }

    fn subject_grade(sub: Subject) {
      match sub {
        Subject::Math(grade) => println!("The Math is {:?}", grade),
        Subject::English(grade) => println!("The Math is {:?}", grade),
      }
    }

    fn main() {
        subject_grade(Subject::Math(Grade::A));
    }

## Rust 运算符

### 比较运算符

:- | :-
--- | ---
`e == f` | `e` 等于 `f`
`e != f` | `e` 不等于 `f`
`e < f` | `e` 小于 `f`
`e > f` | `e` 大于 `f`
`e <= f` | `e` 小于或等于 `f`
`e >= f` | `e` 大于或等于 `f`

    let (e, f) = (1, 100);
    let greater = f > e;        // => true
    let less = f < e;           // => false
    let greater_equal = f >= e; // => true
    let less_equal = e <= f;    // => true
    let equal_to = e == f;      // => false
    let not_equal_to = e != f;  // => true

### 算术运算符

:- | :-
--- | ---
`a + b` | `a` 被添加到 `b`
`a - b` | 从 `a` 中减去`b`
`a / b` | `a` 除以 `b`
`a % b` | 通过与 `b` 相除得到 `a` 的余数
`a * b` | `a` 与 `b` 相乘

    let (a, b) = (4, 5);
    let sum: i32 = a + b;            // => 9
    let subtractions: i32 = a - b;   // => -1
    let multiplication: i32 = a * b; // => 20
    let division: i32 = a / b;       // => 0
    let modulus: i32 = a % b;        // => 4

### 位运算符

运算符 | 描述
--- | ---
`g & h` | 二进制与
`g | h` | 二进制或
`g ^ h` | 二进制异或
`g ~ h` | 二进制补码
`g << h` | 二进制左移
`g >> h` | 二进制右移

    let (g, h) = (0x1, 0x2);
    let bitwise_and = g & h;  // => 0
    let bitwise_or = g | h;   // => 3
    let bitwise_xor = g ^ h;  // => 3
    let right_shift = g >> 2; // => 0
    let left_shift = h << 4;  // => 32

### 逻辑运算符

示例 | 意义
--- | ---
`c && d` | 两者都是真的_(AND)_
`c |
`!c` | `c` 为假 (NOT)

    let (c, d) = (true, false);
    let and = c && d;  // => false
    let or  = c || d;  // => true
    let not = !c;      // => false

### 复合赋值运算符

    let mut k = 9;
    let mut l = k;

运算符 | 描述
--- | ---
`k += l` | 添加一个值并赋值，然后 `k=9`
`k -= l` | `Substrate` 一个值并赋值，然后 `k=18`
`k /= l` | 除以一个值并赋值，然后 `k=9`
`k *= l` | 乘一个值并赋值，然后 `k=81`
`k |= l` | 按位或并赋值，则 `k=89`

## Rust 流程控制

### If 表达式

    let foo = 12;
    let bar = 13;
    if foo == bar {
      println!("foo 等于 bar");
    } else if foo < bar {
      println!("foo 小于 bar");
    } else if foo != bar {
      println!("foo 不等于 bar");
    } else {
      println!("Nothing");
    }

### For 循环

    let mut vec = [1, 2, 3];
    for v in &mut vec {
      *v -= 1;
      println!("v 的值为：{v}");
    }

使用方法 | 等价使用方式 | 所有权
--- | --- | ---
for item in collection | for item in collection.into_iter() | 转移所有权
for item in &collection | for item in collection.iter() | 不可变借用
for item in &mut collection | for item in collection.iter_mut() | 可变借用

### While 循环

    let mut check =  0;
    while check < 11{
      println!("check 是：{check}");
      check += 1;
      println!("递增后：{check}");
      if check == 10{
        break; // 停止 while
      }
    }

### Loop 循环

    loop {
      println!("你好，世界永远！");
    }

无限循环表示

### Continue 继续声明

    for (v, c) in (0..10+1).enumerate(){
      println!("{c} 数字循环");
      if v == 9{
        println!("我们继续？");
        continue;
      }
      println!{"v 的值为：{v}"};
    }

### Break 中断语句

`break` 可以单独使用，也可以带一个返回值

    let mut i = 1;
    let res = loop {
      println!("i 是 {i}");
      if i > 100 {
        break i - 100;
      }
      i *= 2;
    }

    println!("{res}"); // 28

## Rust 模式匹配

### match

match 模式匹配，使用 `a | b` 表示匹配 a 或 b，使用 `_`，表示匹配剩余所有选项

    fn main(){
      let grade = Grade::A;
      match grade {
        Grade::A => println!("Good"),
        Grade::B => println!("Not bad"),
        Grade::C | Grade::D => println!("Come on"),
        _ => println!("emmm"),
      }
    }

    enum Grade {
        A,
        B,
        C,
        D,
        E,
        F,
    }

#### `matches!` 宏

它可以将一个表达式跟模式进行匹配，然后返回匹配的结果 `true` 或 `false`

    assert!(matches!('x' ',A'..='Z' | 'a'..='z'));
    assert!(matches!(Some(101), Some(x) if x > 100));

### if let 匹配

match 表达式需要匹配所有的枚举才能结束，但通常我们只需要匹配我们需要的值

    let x = 3;
    match Some(x) {
      Some(3) => println!("I guess that x is 3"),
      _ => ()
    }

使用 `if let`

    let x = 3;
    if let Some(3) = Some(x) {
        println!("I guess that x is 3");
    }

### while let

    let mut stack = vec![];

    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
        println!("{}", top);
    }

### 其它模式匹配

#### for 循环迭代器

    for (i, v) in collection.iter().enumerate(){}

#### let

    let (x, _, y) = (1, 2, 3);
    println!("{x},{y}");

### 函数中的模式匹配

    fn add((x, y): (i32, i32)) -> i32 {
        x + y
    }
    fn main(){
      let sum = add(1, 2);
      println!("{sum}");
    }

### 忽略参数

#### 使用 `..` 忽略剩余参数

    struct Point {
        x: i32,
        y: i32,
        z: i32,
    }

    let origin = Point { x: 0, y: 0, z: 0 };

    match origin {
        Point { x, .. } => println!("x is {}", x),
    }

#### 使用 `_` 忽略部分参数

    let hello = ('h', 'e', 'l', 'l', 'o');

    match hello {
        (h, _, _, l, o) => {
            println!("char: {}, {}, {}", h, l, o)
        },
    }

### 匹配命名变量

以下代码，只要给定的 x 是 Some 类型，但 Some 中的值不是 1，都会匹配到 y

    let x = Some(10);
    match x {
        Some(1) => println!("x = 1"),
        Some(y) => println!("y = {:?}", y),
        _ => println!("None"),
    }// y = 10

### `@` 绑定

`@` 运算符允许为一个字段绑定另外一个变量。

    let grade = 'A';
    match grade {
        good @ 'A'..='C' => println!("your grade is {}", good),
        _ => println!("Come on"),
    }

    #[derive(Debug)]
    struct Point {
        x: i32,
        y: i32,
    }
    fn main(){
        let p @ Point {x: px, y: py } = Point {x: 10, y: 23};
        println!("x: {}, y: {}", px, py);
        println!("{:?}", p);
    }

如果使用 `|`，需要使用 `()`，进行多个模式的绑定

    match 1 {
        num @ (1 | 2) => {
            println!("{}", num);
        }
        _ => {}
    }

### 使用匹配守卫

    let x = Some(2);
    match x {
        Some(1) => println!("x = 1"),
        Some(y) if y == 2 => println!("y = {:?}", y),
        _ => println!("No match"),
    }// y = 2

## Rust 函数

### 函数命名

rust 的函数使用蛇形命名法（snake case）

    fn print_message(){
      println!("Hello, Quick Reference!");
    }

### 参数值

rust 需要为函数的参数标明确定的类型

    fn another_fn(a:u8, b: &str){
        println!("我是 u8:{}", a);
        println!("我是 &str:{}", b);
    }

    fn main(){
        another_fn(10, "hello")
    }

### 返回值

如果不指定返回值，rust 默认返回 `()` 类型

    // 在 bin 中的入口函数默认返回 ()
    fn main(){}

使用 `->` 指定返回值，如果表达式在最后一行，无需使用 return

    fn add(a:i32, b:i32) -> i32 {
        if a + b < 100 {
            return a - b;
        }
        a + b
    }

### 永不返回 `!`

    fn dead_end() -> ! {
        panic!("panic!!!!!");
    }

## 惯用转换

### &str -> String

    String::from("str");
    "str".to_string();
    "str".to_owned();

### &str -> &[u8]

    "str".as_bytes();

或者你也可以使用 `b""`

    println!("{:?}", b"str");

### &str -> Vec<u8></u8>

    "str".as_bytes().to_vec();
    "str".as_bytes().to_owned();

### String -> &str

    let s = String::from("str");
    let r = s.as_str();

### String -> &[u8]

    let s = String::from("str");
    let v = s.as_bytes();

### String -> Vec<u8></u8>

    let s = String::from("str");
    let v = s.into_bytes();

### &[u8] -> &str

    let b = "str".as_bytes();
    let str = std::str::from_utf8(b).unwrap();

### &[u8] -> String

    let b = "str".as_bytes();
    let str = String::from_utf8(b.to_vec()).unwrap();

### &[u8] -> Vec<u8></u8>

    let b = "str".as_bytes();
    let str = b.to_vec();

    let b = "str".as_bytes();
    let str = b.to_owned();

### Vec<u8> -> &str</u8>

    let b = "str".as_bytes().to_vec();
    let s = std::str::from_utf8(&b).unwrap();

### Vec<u8> -> &[u8]</u8>

    let b = "str".as_bytes().to_vec();
    let s = b.as_slice();

### Vec<u8> -> String</u8>

    let b = "str".as_bytes().to_vec();
    let s = String::from_utf8(b).unwrap();

## 杂项

### 类型断言 type-casting

    let a_int = 90; // int
    // int 到 float
    let mut type_cast = (a_int as f64);

    let orginal: char = 'I';
    // char 到 int => 73
    let type_casted: i64 = orginal as i64;

要在 `Rust` 中执行类型转换，必须使用 `as` 关键字

### 借用

    let mut foo = 4;
    let mut borrowed_foo = &foo;
    println!("{borrowed_foo}");

    let mut bar = 3;
    let mut mutable_borrowed_bar = &mut bar;
    println!("{mutable_borrowed_bar}");

这里借用的值使用 `&` 运算符从值一中借用值

### 解引用

    let mut borrow = 10;
    let deref = &mut borrow;
    println!("{}", *deref);

`*` 操作符用于解引用

### 作用域

    {
      // 范围仅限于此大括号
      let a_number = 1;
    }
    println!("{a_number}");

这将产生错误，因为变量 `a_number` 的生命周期在大括号处结束

## 另见

- Cargo 备忘清单 (jaywcjlove.github.io)
- The Rust Document (doc.rust-lang.org)
- The Rust Reference (doc.rust-lang.org)
- Rust Cheatsheet (phaiax.github.io)
- Rust 标准库文档中文版 (jaywcjlove.github.io)
- Rust 程序设计语言 中文版 (jaywcjlove.github.io)
- Rust By Example 中文版 (jaywcjlove.github.io)
- Rust 参考手册中文版 (jaywcjlove.github.io)
- RustDoc 手册中文版 (jaywcjlove.github.io)
- Rust Cookbook 中文版 (jaywcjlove.github.io)