#hole #macro #struct-fields #structure

perforate

一个宏,用于生成结构体的变体,允许在较长时间内分割字段

1 个不稳定版本

0.1.0 2024年5月15日

#2023Rust 模式

MIT/Apache

16KB
167

Perforate

Perforate 通过生成结构体的变体,允许结构体字段“分割”为与结构体其他部分分离,就像在 分割借用 中的情况。

这类似于使用 mem::take 或其他替换函数的效果,但可以在不实现 Default 或无法构建合适占位符的字段上执行。

用法

在栈上的所有者结构体上穿孔。

use perforate::Perforate;

#[derive(Perforate)]
#[repr(C)]
pub struct TestStruct {
    #[perforate]
    one: String,
    two: u64,
}

let test_struct = TestStruct{one: "one".to_string(), two: 42};

let (perforated, one) = test_struct.perforate_one();
assert_eq!(core::mem::size_of::<TestStruct>(), core::mem::size_of_val(&perforated));
assert_eq!(perforated.two, 42);
assert_eq!(one, "one");

let original = perforated.replace_perf(one);
assert_eq!(original.two, 42);
assert_eq!(original.one, "one");

或在所有者盒子中的结构体上穿孔。

use perforate::Perforate;

#[derive(Perforate)]
#[repr(C)]
pub struct TestStruct {
    #[perforate]
    one: String,
    two: u64,
}

let test_struct = Box::new(TestStruct{one: "one".to_string(), two: 42});

let (perforated_box, one) = TestStruct::boxed_perforate_one(test_struct);
assert_eq!(perforated_box.two, 42);
assert_eq!(one, "one");

let original_box = TestStruct::boxed_replace_one(perforated_box, one);
assert_eq!(original_box.two, 42);
assert_eq!(original_box.one, "one");

注意事项

如果结构体具有仅由带有 #[perforate] 属性的字段使用的泛型参数或生命周期,您必须向您的结构体添加 PhantomData 以防止编译错误。此外,在 问题 合并之前,您不能在 稳定 上对具有泛型类型参数的字段进行穿孔。

您可以访问穿孔结构体的其他“未穿孔”字段,但是穿孔后的结构体是一个新类型,不包含其祖先的任何特性行为。这包括自定义的 Drop 特性。因此,如果您的结构体需要特殊的清理行为,您必须在丢弃之前重新组装它。

依赖关系

~290–740KB
~17K SLoC