#fields #serde #serde-derive #variant #private #derive-debug #untagged-unions

sanitizeable

为不包含某些字段的 derive 结构体

2 个版本

0.1.1 2020 年 8 月 13 日
0.1.0 2020 年 8 月 13 日

#2311Rust 模式

MIT/Apache

4KB
55

不要在生产环境中使用!

  • 它使用了很多 unsafe,虽然有所记录,但只有我自己审查过
  • 它需要 nightly (#![feature(untagged_unions)]#![feature(proc_macro_diagnostic)]
  • 生成的结构体始终是 repr(C)

它做什么?

它允许您将结构体的字段标记为私有,并创建具有或不具有这些字段的结构体变体。然后您可以引用每一个。

它还允许您只为一个或两个结构体添加属性,并将容器消费以将其转换为私有变体。

由于这会破坏内部布局保证,您可能不能在仅一个变体上使用 cfg

你为什么创建这个?

我想自动在编译时确保我不会意外暴露私有数据。

示例

您可以在这里找到更多示例。

#![feature(untagged_unions)]
use sanitizeable::{sanitizeable, Sanitizeable};

#[sanitizeable]
#[derive(Debug)]
#[public_attr::derive(serde::Serialize)] // This only derives `serde::Serialize` for the public variant
struct User {
    name: String,
    // This attrribute is only applied to the field on the private type
    #[private_attr::doc = "This is the user's email, make sure to send them a lot of spam"]
    email: String,
    #[private]
    pin: u16,
}

// using `UserPrivate` here would not compile since it does not implement `serde::Serialize`
fn send_user_information<W: std::io::Write>(writer: &mut W, user_data: &UserPublic) {
    eprintln!("sending user {}", user_data.name);
    serde_json::to_writer(writer, user_data).unwrap();

    // dbg!(user_data.pin); // This would not compile
}

fn change_pin(user: &mut UserPrivate, new_pin: u16) {
    user.pin = new_pin;
}

fn main() {
    let mut user_buffer = Vec::new();

    let mut user = User::from_private(UserPrivate {
        name: "A user".into(),
        email: "[email protected]".into(),
        pin: 1337,
    });

    send_user_information(&mut user_buffer, user.public());

    change_pin(user.private_mut(), 42);

    dbg!(user.public());
}

贡献

如果您觉得这个很酷并希望使其可用,请随意创建 PR、Issue 或给我发消息。

依赖项

~1.5MB
~33K SLoC