通过运行cargo new logic_gates --lib命令创建一个新项目。然后从实现诸如与(and)、异或(xor)等基本的逻辑门函数入手,为他们编写单元测试。接下来,将使用原始的逻辑门函数实现一个半加法器来编写集成测试。在此过程中,还将为程序编写文档。


    1. 首先,我们将从一些单元测试开始。以下是完整的初始代码:
    1. pub fn and(a: u8, b: u8) -> u8 {
    2. unimplemented!()
    3. }
    4. pub fn xor(a: u8, b: u8) -> u8 {
    5. unimplemented!()
    6. }
    7. #[cfg(test)]
    8. mod tests {
    9. use crate::{xor, and};
    10. #[test]
    11. fn test_and() {
    12. assert_eq!(1, and(1,1));
    13. assert_eq!(0, and(0,1));
    14. assert_eq!(0, and(1,0));
    15. assert_eq!(0, and(0,0));
    16. }
    17. #[test]
    18. fn test_xor() {
    19. assert_eq!(1, xor(1,0));
    20. assert_eq!(0, xor(0,0));
    21. assert_eq!(0, xor(1,1));
    22. assert_eq!(1, xor(0,1));
    23. }
    24. }
    1. 我们首先实现了两个逻辑门函数`and``xor`。还有一些运行失败的测试用例,因为它们还没有具体实现。注意,为了表示`0``1`,我们使用`u8`类型,因为`Rust`中没有原生类型用于表示位(`bit`)。现在完善它们的实现以及文档:
    1. ///实现一个逻辑门and,将两个位作为输入,并返回一个位作为输出
    2. //!bit as output
    3. pub fn and(a: u8, b: u8) -> u8 {
    4. match (a, b) {
    5. (1,1) => 1,
    6. _ => 0
    7. }
    8. }
    9. ///实现一个逻辑门xor,将两个位作为输入,并返回一个位作为输出
    10. //!a bit as output
    11. pub fn xor(a: u8, b: u8) -> u8 {
    12. match (a, b) {
    13. (1,0) | (0,1) => 1,
    14. _ => 0
    15. }
    16. }
    1. 在上述代码中,我们只使用`match`表达式表示了`and``xor`逻辑门的真值表。可以看到简洁的表达式如何表示我们的逻辑。现在,可以通过`cargo test`命令运行测试:

    练习:逻辑门模拟器 - 图1

    全部顺利执行!现在准备通过这些逻辑门实现半加法器来编写集成测试。半加法器非常适用作集成测试的示例,因为它们一起使用可以测试程序库的单个组件。在tests/目录下,将创建一个名为half_adder.rs的文件,其中包含如下代码:

    1. use logic_gares::{and, xor};
    2. /*
    3. pub 关键字表示这个类型别名是公开的,即它可以在当前模块之外被访问。
    4. type 关键字用于声明一个类型别名。
    5. Sum 是新声明的类型别名。
    6. u8 是一个无符号的 8 位整数类型,是 Sum 的底层类型。
    7. */
    8. pub type Sum = u8;
    9. pub type Carry = u8;
    10. pub fn half_adder_input_output() -> Vec<((u8, u8), (Sum, Carry))> {
    11. vec![
    12. ((0,0), (0,0)),
    13. ((0,1), (1,0)),
    14. ((1,0), (1,0)),
    15. ((1,1), (0,1)),
    16. ]
    17. }
    18. ///该函数使用原始的逻辑门实现了一个半加法器
    19. fn half_adder(a: u8, b: u8) -> (Sum, Carry){
    20. (xor(a, b), and(a, b))
    21. }
    22. #[test]
    23. fn one_bit_adder() {
    24. for (inn, out) in half_adder_input_output() {
    25. let (a, b) = inn;
    26. println!("Testing: {}, {} -> {:?}", a, b, out);
    27. assert_eq!(half_adder(a, b), out);
    28. }
    29. }
    1. 在上述代码中,我们导入了原始的逻辑门函数`and``xor`。接下来,我们有“`pub type Sum = u8`”这样的代码,它们被称为类型别名(`type alias`)。这在你需要每次输入烦琐的类型名称或者具有复杂特征的类型时非常有用。它为原始的类型赋予了另外一个名称,其纯粹是为了提高可读性和消除歧义。这对`Rust`解析这些类型的方式没有任何影响。然后我们会在`half_adder_input_output`函数中使用`Sum``Carry`,通过它们实现半加法器的真值表。该函数是一个使用方便的辅助函数,可以用于测试后面的`half_adder`函数。`half_adder_inipt_output`函数接受两个位作为输入,并对`Sum``Carry`的值进行计算,并将它们作为`(Sum,Carry)`元组进行返回。然后我们集成测试函数`one_bit_adder`,会对其中的输入/输出对进行迭代,并对`half_adder`的输出进行断言。通过运行`cargo test`命令,得到以下输出结果:

    练习:逻辑门模拟器 - 图2

    接下来让我们通过运行cargo doc --open命令为程序库生成文档。--open标记参数表示在浏览器中为我们打开文档页面。为了对文档进行自定义设置,我们可在程序库文档页面中添加一个图标。为此我们需要在lib.rs文件的顶部添加如下属性:

    练习:逻辑门模拟器 - 图3