成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一起聊聊在Rust中使用枚舉表示狀態

開發 前端
Rust中的枚舉比大多數其他語言更強大。它們可以用來優雅地表示狀態轉換——甚至可以跨越語言邊界。

許多具有系統編程背景的Rust初學者傾向于使用bool(甚至u8—8位無符號整數類型)來表示“狀態”。

例如,如何使用bool來指示用戶是否處于活動狀態?

struct User {
    // ...
    active: bool,
}

一開始,這可能看起來不錯,但是隨著代碼庫的增長,會發現“active”不是二進制狀態。用戶可以處于許多不同的狀態,用戶可能被掛起或刪除。但是,擴展User結構體可能會出現問題,因為代碼的其他部分有可能依賴active是bool類型。

另一個問題是bool不是自文檔化的。active = false是什么意思?用戶是否處于非活動狀態,或者用戶被刪除了,或者用戶被掛起了?我們不知道!

或者,可以使用一個無符號整數來表示狀態:

struct User {
    // ...
    status: u8,
}

這稍微好一點,因為我們現在可以使用不同的值來表示更多的狀態:

const ACTIVE: u8 = 0;
const INACTIVE: u8 = 1;
const SUSPENDED: u8 = 2;
const DELETED: u8 = 3;

let user = User {
    // ...
    status: ACTIVE,
};

u8的一個常見用例是與C代碼交互,在這種情況下,使用u8似乎是唯一的選擇。我們還可以將u8包裝在一個新類型中!

struct User {
    // ...
    status: UserStatus,
}

struct UserStatus(u8);

const ACTIVE: UserStatus = UserStatus(0);
const INACTIVE: UserStatus = UserStatus(1);
const SUSPENDED: UserStatus = UserStatus(2);
const DELETED: UserStatus = UserStatus(3);

let user = User {
    // ...
    status: ACTIVE,
};

這樣我們就可以在UserStatus上定義方法:

impl UserStatus {
    fn is_active(&self) -> bool {
        self.0 == ACTIVE.0
    }
}

我們甚至還可以定義一個構造函數來驗證輸入:

impl UserStatus {
    fn new(status: u8) -> Result<Self, &'static str> {
        match status {
            ACTIVE.0 => Ok(ACTIVE),
            INACTIVE.0 => Ok(INACTIVE),
            SUSPENDED.0 => Ok(SUSPENDED),
            DELETED.0 => Ok(DELETED),
            _ => Err("Invalid status"),
        }
    }
}

使用枚舉表示狀態

枚舉是為域內的狀態建模的好方法。它們以一種非常簡潔的方式表達你的意圖。

#[derive(Debug)]
pub enum UserStatus {
    /// 用戶是活躍的,可以完全訪問他們的帳戶和任何相關功能。
    Active,

    /// 用戶的帳戶處于非活動狀態。該狀態可由用戶或管理員恢復為激活狀態。
    Inactive,

     /// 該用戶的帳戶已被暫時暫停,可能是由于可疑活動或違反政策。
    /// 在此狀態下,用戶無法訪問其帳戶,并且可能需要管理員的干預才能恢復帳戶。
    Suspended,

    /// 該用戶的帳號已被永久刪除,無法恢復。
    /// 與該帳戶關聯的所有數據都可能被刪除,用戶需要創建一個新帳戶才能再次使用該服務。
    Deleted,
}

我們可以將這個枚舉插入到User結構體中:

struct User {
    // ...
    status: UserStatus,
}

但這還不是全部。在Rust中,枚舉比許多其他語言強大得多。例如,可以向枚舉變量中添加數據:

#[derive(Debug)]
pub enum UserStatus {
    Active,
    Inactive,
    Suspended { until: DateTime<Utc> },
    Deleted { deleted_at: DateTime<Utc> },
}

我們還可以表示狀態轉換:

use chrono::{DateTime, Utc};

#[derive(Debug)]
pub enum UserStatus {
    Active,
    Inactive,
    Suspended { until: DateTime<Utc> },
    Deleted { deleted_at: DateTime<Utc> },
}

impl UserStatus {
    /// 暫停用戶直到指定日期
    fn suspend(&mut self, until: DateTime<Utc>) {
        match self {
            UserStatus::Active => *self = UserStatus::Suspended { until },
            _ => {}
        }
    }

    /// 激活用戶
    fn activate(&mut self) -> Result<(), &'static str> {
        match self {
            // A deleted user can't be activated!
            UserStatus::Deleted { .. } => return Err("can't activate a deleted user"),
            _ => *self = UserStatus::Active
        }
        Ok(())
    }

    /// 刪除用戶,這是一個永久的動作!
    fn delete(&mut self) {
        if let UserStatus::Deleted { .. } = self {
            // 已經刪除,不要再設置deleted_at字段。
            return;
        }
        *self = UserStatus::Deleted {
            deleted_at: Utc::now(),
        }
    }

    fn is_active(&self) -> bool {
        matches!(self, UserStatus::Active)
    }

    fn is_suspended(&self) -> bool {
        matches!(self, UserStatus::Suspended { .. })
    }

    fn is_deleted(&self) -> bool {
        matches!(self, UserStatus::Deleted { .. })
    }
}

#[cfg(test)]
mod tests {
    use chrono::Duration;
    use super::*;

    #[test]
    fn test_user_status() -> Result<(), &'static str>{
        let mut status = UserStatus::Active;
        assert!(status.is_active());
        // 暫停到明天
        status.suspend(Utc::now() + Duration::days(1));
        assert!(status.is_suspended());
        status.activate()?;
        assert!(status.is_active());
        status.delete();
        assert!(status.is_deleted());
        Ok(())
    }

    #[test]
    fn test_user_status_transition() {
        let mut status = UserStatus::Active;
        assert!(status.is_active());
        status.delete();
        assert!(status.is_deleted());
        // 無法激活已刪除的用戶
        assert!(status.activate().is_err());
    }
}

看看我們僅僅用幾行代碼就涵蓋了多少內容!我們可以放心地擴展應用程序,因為我們知道不會意外地刪除用戶兩次或重新激活已刪除的用戶。非法的狀態轉換現在是不可能的!

使用枚舉與C代碼交互

C代碼:

typedef struct {
    uint8_t status;
} User;

User *create_user(uint8_t status);

你可以寫一個Rust枚舉來表示狀態:

#[repr(u8)]
#[derive(Debug, PartialEq)]
pub enum UserStatus {
    Active = 0,
    Inactive,
    Suspended,
    Deleted,
}

impl TryFrom<u8> for UserStatus {
    type Error = ();

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            0 => Ok(UserStatus::Active),
            1 => Ok(UserStatus::Inactive),
            2 => Ok(UserStatus::Suspended),
            3 => Ok(UserStatus::Deleted),
            _ => Err(()),
        }
    }
}

注意到#[repr(u8)]屬性了嗎?它告訴編譯器將此枚舉表示為無符號8位整數。這對于與C代碼的兼容性至關重要。

現在,讓我們用一個安全的Rust包裝器包裝C函數:

extern "C" {
    fn create_user(status: u8) -> *mut User;
}

pub fn create_user_wrapper(status: UserStatus) -> Result<User, &'static str> {
    let user = unsafe { create_user(status as u8) };
    if user.is_null() {
        Err("Failed to create user")
    } else {
        Ok(unsafe { *Box::from_raw(user) })
    }
}

Rust代碼現在使用豐富的enum類型與C代碼通信。

總結

Rust中的枚舉比大多數其他語言更強大。它們可以用來優雅地表示狀態轉換——甚至可以跨越語言邊界。

責任編輯:武曉燕 來源: coding到燈火闌珊
相關推薦

2024-01-02 09:09:03

枚舉規范化管理

2023-10-31 14:04:17

Rust類型編譯器

2021-09-11 19:02:34

Hook使用版本

2023-08-10 08:28:46

網絡編程通信

2023-08-04 08:20:56

DockerfileDocker工具

2023-06-30 08:18:51

敏捷開發模式

2022-05-24 08:21:16

數據安全API

2023-09-10 21:42:31

2023-09-21 08:16:56

JDK 21向量計算計算

2024-02-20 21:34:16

循環GolangGo

2021-08-27 07:06:10

IOJava抽象

2022-12-07 09:01:14

布局容器VStack?

2024-07-18 08:54:49

2021-07-12 11:35:13

Go協程Goroutine

2023-03-26 23:47:32

Go內存模型

2024-07-26 09:47:28

2022-10-08 00:00:05

SQL機制結構

2023-07-24 09:41:08

自動駕駛技術交通

2022-02-23 08:41:58

NATIPv4IPv6

2022-09-22 08:06:29

計算機平板微信
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 秋霞电影一区二区三区 | 亚洲精品免费在线 | 伊人久久综合 | 国产精品精品久久久 | 欧美成人高清视频 | 夜夜爽99久久国产综合精品女不卡 | 国产精品久久久久久久久动漫 | 国产精品s色 | 久久四虎 | 在线伊人 | 区一区二在线观看 | 午夜免费看 | 插插插干干干 | 久久综合久久自在自线精品自 | 欧美理伦片在线播放 | 国产精品视频一区二区三区 | www狠狠爱com | 国产 欧美 日韩 一区 | 日韩av在线中文字幕 | 在线观看www视频 | 亚洲精品国产成人 | 91久久北条麻妃一区二区三区 | 国产精品视频久久久 | 自拍偷拍3p| 成人av在线播放 | 成年人网站国产 | 国产精品视频久久 | 伊人伊人伊人 | 一级片网址| 亚洲香蕉在线视频 | 97伦理| 在线免费av观看 | 久久精品国产亚洲a | 久久国内 | 日本不卡一区 | 国产日韩欧美在线观看 | 亚洲精品日韩精品 | 欧美中文字幕在线观看 | 一区二区三区视频在线免费观看 | 四虎影院免费在线播放 | 81精品国产乱码久久久久久 |