最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從迷你todo?命令行入門Rust示例詳解

 更新時間:2023年01月10日 08:52:34   作者:PuffMeow  
這篇文章主要為大家介紹了從一個迷你todo命令行入門Rust的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一個迷你 todo 應(yīng)用

該文章將使用 Rust 從零去做一個入門級別的 TODO 命令行應(yīng)用

你將學(xué)會什么?

  • 基本的命令行操作
  • 文件讀寫和文件結(jié)構(gòu)組織

我們將會通過命令行輸入來實(shí)現(xiàn)對根目錄下 state.json 文件的編輯,如:

cargo run create 買菜

cargo run get 買菜

cargo run delete 買菜

cargo run edit 買菜

我們的 todo 狀態(tài)會有 pending 和 done 這兩種,create 操作將創(chuàng)建一個 {"買菜":"pending"} 的狀態(tài),edit 操作主要就是將 pending 狀態(tài)轉(zhuǎn)變?yōu)?done 狀態(tài)

需要安裝的依賴

我們要操作 json 數(shù)據(jù)結(jié)構(gòu),所以要安裝下面這個 crate

[package]
edition = "2021"
name = "todo_app"
version = "0.1.0"
[dependencies]
serde_json = {default-feature = false, version = "1.0", feature = ["alloc"]}

文件目錄組織

|   main.rs               主文件
|   process.rs            處理 todo 命令行輸入
|   state.rs              讀寫文件
|
\---todo
    |   mod.rs            類似于 js 里面的 index.js
    |
    \---structs           struct 數(shù)據(jù)結(jié)構(gòu)組織
        |   base.rs       基礎(chǔ)參數(shù)的數(shù)據(jù)結(jié)構(gòu)
        |   done.rs       完成狀態(tài)的數(shù)據(jù)結(jié)構(gòu)
        |   mod.rs        類似于 js 里面的 index.js
        |   pending.rs    處理中狀態(tài)的數(shù)據(jù)結(jié)構(gòu)
        |
        \---traits        (特征)類似于 ts 里面的 interface
                create.rs 創(chuàng)建操作
                delete.rs 刪除操作
                edit.rs   編輯操作
                get.rs    查詢操作
                mod.rs    類似于 js 里面的 index.js

主文件

// 有一點(diǎn)點(diǎn)像 import process from './process.rs'
mod process;
mod state;
mod todo;
// 使用外部的庫、標(biāo)準(zhǔn)庫或自己定義的工具
use process::process_input;
use serde_json::Map;
use serde_json::Value;
use state::read_file;
use std::env;
use todo::todo_factory;
fn main() {
    // 收集所有命令行的參數(shù),轉(zhuǎn)換成數(shù)組
    let args: Vec<String> = env::args().collect();
    // 拿到第一個參數(shù)如 get、delete、edit、create
    let command: &String = &args[1];
    // 第二個參數(shù)是用來記錄事件的
    let title: &String = &args[2];
    // 讀取根目錄的 state.json 文件并轉(zhuǎn)換成 map json 結(jié)構(gòu)
    let state: Map<String, Value> = read_file("./state.json");
    // 如果事件已經(jīng)存取過了,那就直接獲取,沒有就將其狀態(tài)設(shè)置為 pending
    let status: String;
    match &state.get(title) {
        Some(result) => status = result.to_string().replace('\"', ""),
        None => status = "pending".to_string(),
    }
    // todo_factory 工廠函數(shù)用于處理 pending 和 done 狀態(tài)的輸入
    let item = todo_factory(&status, title).expect(&status);
    // 將狀態(tài)輸入到本地文件中
    process_input(item, command.to_string(), &state);
}

上面我們看到了 3 個主要我們需要自己編寫的函數(shù):

  • read_file 讀取文件
  • todo_factory 狀態(tài)工廠函數(shù)
  • process_input 處理輸入

接下來讓我們一個一個來看下這幾個函數(shù)

讀取文件

read_file 函數(shù)位于 src/state.rs 路徑下,該文件主要是用來存儲狀態(tài)操作的,里面包含讀取和寫入兩個函數(shù),讓我們主要看下 read_file 這個函數(shù),它的功能:

  • 打開文件
  • 讀取文件
  • 將讀取到的文件內(nèi)容轉(zhuǎn)成 json 對象
  • 返回讀取到的 json 對象
use std::fs::{self, File};
use std::io::Read;
use serde_json::json;
use serde_json::value::Value;
use serde_json::Map;
/** 讀取文件 */
pub fn read_file(file_name: &str) -> Map<String, Value> {
    // 打開文件
    let mut file = File::open(file_name).unwrap();
    // 創(chuàng)建一個 string buffer 用于存儲數(shù)據(jù)
    let mut data = String::new();
    // 讀取數(shù)據(jù)寫入到 buffer
    file.read_to_string(&mut data).unwrap();
    // 將讀取到的字符串轉(zhuǎn)換成 json 文本格式 Value 類型
    let json: Value = serde_json::from_str(&data).unwrap();
    // 將 json 文本格式轉(zhuǎn)換成 json 對象
    let state: Map<String, Value> = json.as_object().unwrap().clone();
    // 將這個對象返回出去
    return state;
}
/** 寫入文件 */
pub fn write_to_file(file_name: &str, state: &mut Map<String, Value>) {
    // json! 這個宏用于將 json 字面量對象轉(zhuǎn)換回 json 文本 Value 格式
    let new_data = json!(state);
    // 將 json 文本寫入到文件中
    fs::write(file_name, new_data.to_string()).expect("unable to write to file");
}

狀態(tài)處理工廠函數(shù)

看完文件讀取操作我們再來看下第二個主要函數(shù) todo_factory,這個函數(shù)主要是根據(jù)事件的狀態(tài)和通過命令行輸入的 title 事件名稱,然后構(gòu)建出一個相應(yīng)的數(shù)據(jù)結(jié)構(gòu)

該文件位于 src/todo/mod.rs 路徑下

它的作用主要是根據(jù)輸入的 pending/done 狀態(tài),然后創(chuàng)建出一個對應(yīng)的數(shù)據(jù)結(jié)構(gòu)

// 將 structs 向外部導(dǎo)出
pub mod structs;
use structs::done::Done;
use structs::pending::Pending;
// 創(chuàng)建一個包含 pending 和 done 狀態(tài)的枚舉
pub enum ItemTypes {
    Pending(Pending),
    Done(Done),
}
/** 狀態(tài)處理工廠函數(shù) */
pub fn todo_factory(item_type: &str, item_title: &str) -> Result<ItemTypes, &'static str> {
    match item_type {
        "pending" => {
            // 創(chuàng)建一個 pending 狀態(tài)的數(shù)據(jù)結(jié)構(gòu),然后返回出去
            let pending_item = Pending::new(item_title);
            Ok(ItemTypes::Pending(pending_item))
        }
        "done" => {
            // 創(chuàng)建一個 done 狀態(tài)的數(shù)據(jù)結(jié)構(gòu),然后返回出去
            let done_item = Done::new(item_title);
            Ok(ItemTypes::Done(done_item))
        }
        // 如果不是這兩個狀態(tài)就返回一個錯誤
        _ => Err("This is not accepted!"),
    }
}

從上面的代碼中我們可以看到下面這兩行代碼,這是我們主要需要定義的兩個狀態(tài)數(shù)據(jù)結(jié)構(gòu),他們位于 src/todo/structs 路徑下

use structs::done::Done;
use structs::pending::Pending;

不過在看上面兩個數(shù)據(jù)結(jié)構(gòu)之前,我們需要先來看下另一個基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),就是 base,因?yàn)樯厦鎯蓚€數(shù)據(jù)結(jié)構(gòu)是基于 base 的,實(shí)現(xiàn)一個類似于面向?qū)ο笳Z言里繼承的做法,base 是它們倆的基類

該文件位于 src/todo/structs/base.rs 路徑下

pub struct Base {
    pub title: String,
    pub status: String,
}
// 為這個 Base 數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)一個 new 方法,并返回一個實(shí)例化后的數(shù)據(jù)結(jié)構(gòu)
impl Base {
    pub fn new(input_title: &str, input_status: &str) -> Base {
        Base {
            title: input_title.to_string(),
            status: input_status.to_string(),
        }
    }
}

現(xiàn)在我們用 Pending 和 Done 兩個 struct 來 "繼承" Base

該文件位于 src/todo/structs/pending.rs 路徑下

use super::base::Base;
pub struct Pending {
    pub super_struct: Base,
}
impl Pending {
    pub fn new(input_title: &str) -> Pending {
        Pending {
            super_struct: Base::new(input_title, "pending"),
        }
    }
}

該文件位于 src/todo/structs/done.rs 路徑下

use super::base::Base;
pub struct Done {
    pub super_struct: Base,
}
impl Done {
    pub fn new(input_title: &str) -> Done {
        Done {
            super_struct: Base::new(input_title, "done"),
        }
    }
}

Trait(特征)

Trait 類似于 TS 里的 interface 接口,現(xiàn)在我們要為我們的 struct 來實(shí)現(xiàn)一些在 Trait 里面定義的方法,文件路徑在 src/todo/structs/traits

Create trait

文件路徑在 src/todo/structs/traits/create

use serde_json::{json, Map, Value};
use crate::state::write_to_file;
pub trait Create {
    // 為這個 trait 實(shí)現(xiàn)一個默認(rèn)的 create 方法
    fn create(&self, title: &String, status: &String, state: &mut Map<String, Value>) {
        state.insert(title.to_string(), json!(status));
        write_to_file("./state.json", state);
        println!("\n\n{} is being created\n\n", title);
    }
}

Get trait

文件路徑在 src/todo/structs/traits/get

use serde_json::{Map, Value};
pub trait Get {
    fn get(&self, title: &String, state: &Map<String, Value>) {
        let item = state.get(title);
        match item {
            Some(result) => {
                println!("\n\nItem: {}", title);
                println!("Status: {} \n\n", result);
            }
            None => println!("item: {} was not find", title),
        }
    }
}

Delete trait

文件路徑在 src/todo/structs/traits/delete

use serde_json::{Map, Value};
use crate::state::write_to_file;
pub trait Delete {
    fn delete(&self, title: &String, state: &mut Map<String, Value>) {
        state.remove(title);
        write_to_file("./state.json", state);
        println!("\n\n{} is being deleted\n\n", title);
    }
}

Edit trait

該 Trait 主要實(shí)現(xiàn)兩個方法,一個是將事件設(shè)置為 pending 狀態(tài),一個將事件設(shè)置為 done 狀態(tài)

文件路徑在 src/todo/structs/traits/edit

use serde_json::{json, Map, Value};
use crate::state::write_to_file;
pub trait Edit {
    fn set_to_done(&self, title: &String, state: &mut Map<String, Value>) {
        state.insert(title.to_string(), json!("done".to_string()));
        write_to_file("./state.json", state);
        println!("\n\n{} is being set to done\n\n", title);
    }
    fn set_to_pending(&self, title: &String, state: &mut Map<String, Value>) {
        state.insert(title.to_string(), json!("pending".to_string()));
        write_to_file("./state.json", state);
        println!("\n\n{} is being set to pending\n\n", title);
    }
}

導(dǎo)出 trait

文件路徑在 src/todo/structs/traits/mod

pub mod create;
pub mod delete;
pub mod edit;
pub mod get;

為 struct 實(shí)現(xiàn) trait

接下來我們?yōu)?Pending 和 Done 兩個 struct 來實(shí)現(xiàn)這幾個 trait

Pending

我們?yōu)?Pending 實(shí)現(xiàn)所有的 4 個 trait

use super::base::Base;
use super::traits::create::Create;
use super::traits::delete::Delete;
use super::traits::edit::Edit;
use super::traits::get::Get;
pub struct Pending {
    pub super_struct: Base,
}
impl Pending {
    pub fn new(input_title: &str) -> Pending {
        Pending {
            super_struct: Base::new(input_title, "pending"),
        }
    }
}
impl Delete for Pending {}
impl Create for Pending {}
impl Edit for Pending {}
impl Get for Pending {}

Done

為 Done 實(shí)現(xiàn)除了 Create 以外的 trait

文件路徑在 src/todo/structs/done

use super::base::Base;
use super::traits::delete::Delete;
use super::traits::edit::Edit;
use super::traits::get::Get;
pub struct Done {
    pub super_struct: Base,
}
impl Done {
    pub fn new(input_title: &str) -> Done {
        Done {
            super_struct: Base::new(input_title, "done"),
        }
    }
}
impl Delete for Done {}
impl Edit for Done {}
impl Get for Done {}

導(dǎo)出 struct

mod base;
pub mod done;
pub mod pending;
pub mod traits;

Process 輸入處理

文件位于 src/process.rs 路徑下

use serde_json::{Map, Value};
use crate::todo::{
    structs::{
        done::Done,
        pending::Pending,
        traits::{create::Create, delete::Delete, edit::Edit, get::Get},
    },
    ItemTypes,
};
// 處理 pending 狀態(tài)
fn process_pending(item: Pending, command: String, state: &Map<String, Value>) {
    let mut state = state.clone();
    // 根據(jù)用戶的輸入來調(diào)用不同的方法
    match command.as_str() {
        "get" => item.get(&item.super_struct.title, &state),
        "create" => item.create(
            &item.super_struct.title,
            &item.super_struct.status,
            &mut state,
        ),
        "delete" => item.delete(&item.super_struct.title, &mut state),
        "edit" => item.set_to_done(&item.super_struct.title, &mut state),
        _ => println!("command: {} is not supported", command),
    }
}
// 處理 done 狀態(tài)
fn process_done(item: Done, command: String, state: &Map<String, Value>) {
    let mut state = state.clone();
    match command.as_str() {
        "get" => item.get(&item.super_struct.title, &state),
        "delete" => item.delete(&item.super_struct.title, &mut state),
        "edit" => item.set_to_pending(&item.super_struct.title, &mut state),
        _ => println!("command: {} is not supported", command),
    }
}
// 處理用戶的輸入,根據(jù)輸入來匹配枚舉,然后執(zhí)行不同的操作
pub fn process_input(item: ItemTypes, command: String, state: &Map<String, Value>) {
    match item {
        ItemTypes::Pending(item) => process_pending(item, command, state),
        ItemTypes::Done(item) => process_done(item, command, state),
    }
}

最后

按照上面的代碼一步一步來完成就可以執(zhí)行程序了,在根目錄下新建一個 state.json 文件,寫入一個空對象,不然會報錯(代碼沒做處理)

{}

最后再在控制臺上去執(zhí)行

cargo run create shopping

然后就能看到 state.json 中多了一條記錄

{ "shopping": "pending" }

其它的方法就交由你們自己去嘗試好了~

以上就是從迷你 todo 命令行入門 Rust的詳細(xì)內(nèi)容,更多關(guān)于todo 命令行入門Rust的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • rust智能指針的具體使用

    rust智能指針的具體使用

    智能指針是一些數(shù)據(jù)結(jié)構(gòu),它們的行為類似于指針但擁有額外的元數(shù)據(jù)和附加功能,本文就來介紹一下rust智能指針的具體使用,感興趣的可以了解一下
    2023-12-12
  • Rust語言開發(fā)環(huán)境搭建詳細(xì)教程(圖文教程)

    Rust語言開發(fā)環(huán)境搭建詳細(xì)教程(圖文教程)

    本文主要介紹了rust編程語言在windows上開發(fā)環(huán)境的搭建方法,文中通過圖文的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • Rust中不可變變量與const的區(qū)別詳解

    Rust中不可變變量與const的區(qū)別詳解

    Rust作者認(rèn)為變量默認(rèn)應(yīng)該是immutable,即聲明后不能被改變的變量,這一點(diǎn)是讓跨語言學(xué)習(xí)者覺得很別扭,不過這一點(diǎn)小的改變帶來了諸多好處,本節(jié)我們來學(xué)習(xí)Rust中不可變變量與const的區(qū)別,需要的朋友可以參考下
    2024-02-02
  • Rust重載運(yùn)算符之復(fù)數(shù)四則運(yùn)算的實(shí)現(xiàn)

    Rust重載運(yùn)算符之復(fù)數(shù)四則運(yùn)算的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Rust如何實(shí)現(xiàn)復(fù)數(shù)以及復(fù)數(shù)的四則運(yùn)算,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-08-08
  • Rust中的Cargo構(gòu)建、運(yùn)行、調(diào)試

    Rust中的Cargo構(gòu)建、運(yùn)行、調(diào)試

    Cargo是rustup安裝后自帶的,Cargo?是?Rust?的構(gòu)建系統(tǒng)和包管理器,這篇文章主要介紹了Rust之Cargo構(gòu)建、運(yùn)行、調(diào)試,需要的朋友可以參考下
    2022-09-09
  • Rust使用libloader調(diào)用動態(tài)鏈接庫

    Rust使用libloader調(diào)用動態(tài)鏈接庫

    這篇文章主要為大家介紹了Rust使用libloader調(diào)用動態(tài)鏈接庫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 關(guān)于Rust命令行參數(shù)解析以minigrep為例

    關(guān)于Rust命令行參數(shù)解析以minigrep為例

    本文介紹了如何使用Rust的std::env::args函數(shù)來解析命令行參數(shù),并展示了如何將這些參數(shù)存儲在變量中,隨后,提到了處理文件和搜索邏輯的步驟,包括讀取文件內(nèi)容、搜索匹配項和輸出搜索結(jié)果,最后,總結(jié)了Rust標(biāo)準(zhǔn)庫在命令行參數(shù)處理中的便捷性和社區(qū)資源的支持
    2025-02-02
  • 使用環(huán)境變量實(shí)現(xiàn)Rust程序中的不區(qū)分大小寫搜索方式

    使用環(huán)境變量實(shí)現(xiàn)Rust程序中的不區(qū)分大小寫搜索方式

    本文介紹了如何在Rust中實(shí)現(xiàn)不區(qū)分大小寫的搜索功能,并通過測試驅(qū)動開發(fā)(TDD)方法逐步實(shí)現(xiàn)該功能,通過修改運(yùn)行函數(shù)和獲取環(huán)境變量,程序可以根據(jù)環(huán)境變量控制搜索模式
    2025-02-02
  • Rust讀取配置文件的實(shí)現(xiàn)步驟

    Rust讀取配置文件的實(shí)現(xiàn)步驟

    任何項目都離不開對于配置文件的讀取和解析,rust項目也一樣,本文主要介紹了Rust讀取配置文件的實(shí)現(xiàn)步驟,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • rust多個mod文件引用和文件夾mod使用注意事項小結(jié)

    rust多個mod文件引用和文件夾mod使用注意事項小結(jié)

    在 Rust 項目中,可以使用 mod 關(guān)鍵字將一個文件夾或一個 rs 文件作為一個模塊引入到當(dāng)前文件中,本文給大家介紹rust多個mod文件引用和文件夾mod使用注意事項小結(jié),感興趣的朋友跟隨小編一起看看吧
    2024-03-03

最新評論

兴山县| 诸暨市| 开江县| 内江市| 余庆县| 双辽市| 淮北市| 友谊县| 个旧市| 镇巴县| 南开区| 彝良县| 慈利县| 肥西县| 衡阳市| 集贤县| 枞阳县| 济南市| 通城县| 汽车| 茶陵县| 泗阳县| 贞丰县| 城固县| 阳高县| 台东市| 翁牛特旗| 百色市| 温泉县| 图木舒克市| 陈巴尔虎旗| 安化县| 邹平县| 昌乐县| 万全县| 逊克县| 定西市| 庄浪县| 湖口县| 尼玛县| 陵川县|