#fields #derive #attr #variant #private #public #sanitizeable

nightly sanitizeable_derive

不包含特定字段的 derive 结构体

2个版本

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

#21#attr


sanitizeable 中使用

MIT/Apache

21KB
445

不要在生产环境中使用!

  • 它使用了大量的 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
~35K SLoC