Rust中non_exhaustive的enum使用确保程序健壮性

 更新时间:2023年11月03日 10:29:17   作者:da_miao_zi  
这篇文章主要为大家介绍了Rust中non_exhaustive的enum使用确保程序健壮性示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

Rust中non_exhaustive的enum

所谓non_exhaustive的enum就是定义中带有#[non_exhaustive]enum,如

#[non_exhaustive]
pub enum Error {
    Message(String),
    Other,
}

在定义了这个enum的crate中,non_exhaustive没有任何效果。

let error = Error::Other;
// Non-exhaustive enums can be matched on exhaustively within the defining crate.
match error {
    Error::Message(ref s) => { },
    Error::Other => { },
}

但若引用的crate中存在non_exhaustiveenum,会发生什么呢?

以libpnet这个crate为例

https://docs.rs/pnet/latest/pnet/#这个页面给出的示例代码中,可以看到这么一段

// Create a new channel, dealing with layer 2 packets
let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) {
    Ok(Ethernet(tx, rx)) => (tx, rx),
    Ok(_) => panic!("Unhandled channel type"),
    Err(e) => panic!("An error occurred when creating the datalink channel: {}", e)
};

datalink::channel()的返回值类型为Result<Channel, Error>,而Channel的类型是一个enum,

pub enum Channel {
    Ethernet(Box<dyn DataLinkSender, Global>, Box<dyn DataLinkReceiver, Global>),
}

atalink::channel()返回结果分析

如果datalink::channel()返回的是成功的结果(类型为Channel),将与第一个Ok(Ethernet(tx, rx))模式的前半部分匹配(因为Ok()就对应成功的结果)。

而根据Channel的定义,Channel::Ethernet(tx, rx)是该enum唯一的成员(variant),所以只要是成功的结果,就应该匹配第1个模式,否则就匹配最后的Err(e)这个模式。

这看起来满足Rust中的匹配必须是穷举式的(exhaustive)这一要求。因此似乎第2个模式Ok(_) => ,就显得多余了。但若去掉这行,编译时就会报错Ok(_) not covered

error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
  --> src/main.rs:33:31
   |
33 |     let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
   |
note: `Result<Channel, std::io::Error>` defined here
...
   |
   = note: not covered
   = note: the matched value is of type `Result<Channel, std::io::Error>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
   |
38 ~         },
39 +         Ok(_) => todo!()
   |

For more information about this error, try `rustc --explain E0004`.

这背后的原因就是因为enum Channelnon_exhaustive的,其完整定义是

// https://docs.rs/pnet_datalink/0.34.0/src/pnet_datalink/lib.rs.html#99
/// A channel for sending and receiving at the data link layer.
#[non_exhaustive]
pub enum Channel {
    /// A datalink channel which sends and receives Ethernet packets.
    Ethernet(Box<dyn DataLinkSender>, Box<dyn DataLinkReceiver>),
}

而我们又在外部引用了包含这个enum的crate。解决的办法就是加入Ok(_) => {...}

感觉这应该算Rust确保程序健壮性(鲁棒性)的一方面,在编译阶段就报出潜在的错误——咱也不知道引用的crate什么时候会在enum中增加新的成员。

参考

https://doc.rust-lang.org/beta/reference/attributes/type_syst... Type system attributes

https://docs.rs/pnet/latest/pnet/#examples This (fairly useless) code implements an Ethernet echo server.

以上就是Rust中non_exhaustive的enum使用确保程序健壮性的详细内容,更多关于Rust 的资料请关注程序员之家其它相关文章!

相关文章

  • rust多样化错误处理(从零学习)

    rust多样化错误处理(从零学习)

    一个优秀的项目,错误处理的优雅性是至关重要的,而rust,anyhow creat是绕不过去的一个,今天我们来研究下,怎么使用它,帮助我们写出更优雅的代码,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2023-11-11
  • Rust 中的文件操作示例详解

    Rust 中的文件操作示例详解

    Rust 中的路径操作是跨平台的,std::path 模块提供的了两个用于描述路径的类型,本文给大家介绍Rust 中的文件操作示例详解,感兴趣的朋友一起看看吧
    2021-11-11
  • Rust读取配置文件的实现

    Rust读取配置文件的实现

    本文主要介绍了Rust读取配置文件的实现,主要读取Cargo.toml文件,读取.env文件和读取自定义toml文件这三种,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Rust指南之泛型与特性详解

    Rust指南之泛型与特性详解

    泛型机制是编程语言用于表达类型抽象的机制,一般用于功能确定、数据类型待定的类,如链表、映射表等,这篇文章主要介绍了Rust指南泛型与特性,需要的朋友可以参考下
    2022-10-10
  • 如何在Rust中处理命令行参数和环境变量

    如何在Rust中处理命令行参数和环境变量

    在本章节中, 我们探讨了Rust处理命令行参数的常见的两种方式和处理环境变量的两种常见方式,感兴趣的朋友一起看看吧
    2023-12-12
  • rust异步编程详细讲解

    rust异步编程详细讲解

    这篇文章主要介绍了rust异步编程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • 用rust?写一个jar包?class冲突检测工具

    用rust?写一个jar包?class冲突检测工具

    这篇文章主要介绍了用rust?写一个jar包?class冲突检测工具?的相关资料,需要的朋友可以参考下
    2023-05-05
  • Rust中的引用与借用举例详解

    Rust中的引用与借用举例详解

    这篇文章主要给大家介绍了关于Rust中引用与借用的相关资料,rust中借用和引用的附带功效都一样,就是都有生命周期,文中通过代码介绍的非常详细,对大家学习或者使用Rust具有一定的参考价值,需要的朋友可以参考下
    2023-11-11
  • Rust动态数组Vec基本概念及用法

    Rust动态数组Vec基本概念及用法

    Rust中的Vec是一种动态数组,它可以在运行时自动调整大小,本文主要介绍了Rust动态数组Vec基本概念及用法,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • 解析rust中的struct

    解析rust中的struct

    自定义的数据类型,为相关联的值命名,打包成有意义的组合,类似python的dict,但是赋值的时候可以不按顺序,本文给大家介绍下rust中的struct知识,感兴趣的朋友一起看看吧
    2022-10-10

最新评论

?


http://www.vxiaotou.com