8个版本

0.1.8 2022年6月27日
0.1.7 2022年6月27日

#1046数据结构

每月30次下载
corresponding-macros 中使用

MIT 许可证

10KB

对应

这个Rust包可以用于在模块内复制结构体。只有同名同型的字段会被复制,因此包名为对应。

通过在模块上添加属性 derive_corresponding,将 MoveCorresponding 特性实现为模块内所有的结构体。这使得可以在具有属性模块的所有结构体上调用 move_corresponding 函数,并将模块内的所有结构体作为参数。对于模块中所有派生自 Default 的结构体,将实现 From 特性。

示例

在一个模块上添加 derive_corresponding 属性。这个模块必须声明为内联。

use corresponding::derive_corresponding;

#[derive_corresponding]
mod my_mod {
    #[derive(Debug, Default)]
    pub struct A {
        pub a: u8,
        pub b: u8,
        pub c: u8,
    }

    #[derive(Debug, Clone)]
    pub struct B {
        pub a: u8,
        pub b: Option<u8>,
        pub d: u8,
    }
}

确保 MoveCorresponding 在作用域内,并开始从 B 移动对应的字段到 A,反之亦然

use corresponding::MoveCorresponding;
use my_mod::*;

fn start_moving() {
    let mut a = A { a: 1, b: 1, c: 1 };
    let mut b = B { a: 2, b: Some(2), d: 2 };

    a.move_corresponding(b.clone());
    println!("{a:?}");      // Output: A { a: 2, b: 2, c: 1 }

    let a2 = A { a: 3, b: 3, c: 3 };
    b.move_corresponding(a2);
    println!("{b:?}");      // Output: B { a: 3, b: Some(3), d: 2 }
}

因为结构体 A 派生自 Default,它也会实现 From。所以你可以将 B 转换为 A

fn start_transforming() {
    let b = B { a: 4, b: Some(4), d: 4 };
    
    let a: A = b.into();
    println!("{a:?}");      // Output: A { a: 4, b: 4, c: 0 }
}

结构体 B 没有派生自 Default,因此你不能将 A 转换为 B。在这种情况下没有实现 From

还可以在 examples 文件夹中看到一个工作示例。

选项

同时,类型为 TOption<T> 的字段也被认为是对应的。

  • Option<T> 移动到 T 时,只有当源字段是 Some() 时,才会设置目标字段
  • T 移动到 Option<T> 将始终将目标字段设置为 Some(value)
  • Option<T> 移动到 Option<T> 只在源字段为 Some(value) 时设置目标字段

这意味着无法使用 move_correspondingOption 设置为 None

不支持更深层次的 Option,因此 Option<Option<V>> 被视为 Option<T>,其中 T = Option<V>

展开

如果您已安装 cargo-expand,您可以通过运行来查看生成的实现

$ cd corresponding
$ cargo expand --example corresponding

依赖关系

~1.5MB
~36K SLoC