Field attributes
attributes that can be applied to a struct field, enum variant or field in an enum variant
as
Provide a value that the given field/variant should be set to when expunged. e.g. "<expunged>".to_string()
use expunge::Expunge;
#[derive(Expunge)]
#[expunge(as = "<redacted>".to_string())]
struct ConnectionInfo {
username: String,
password: String,
host: String,
}
default
Shorthand for as = Default::default()
Example:
use expunge::Expunge;
#[derive(Default)]
struct Location(f64, f64);
#[derive(Expunge)]
struct UserData {
username: String,
password: String,
#[expunge(default)]
location: Location,
}
with
Expunge the field/variant using this function.
It must return the same type as it takes. e.g. hash a String
with sha256::digest
If you own the type, then could also implement Expunge
directly.
Using with
, however, allows you to use different transformations for different fields of the same type.
Example:
use expunge::Expunge;
fn redact_first_char(mut s: String) -> String {
s.replace_range(0..1, "*");
s
}
fn char_count_of(s: String) -> String{
s.len().to_string()
}
#[derive(Expunge)]
#[cfg_attr(test, derive(Eq, PartialEq, Debug), expunge(allow_debug))]
struct User {
username: String,
#[expunge(with = char_count_of)]
first_name: String,
#[expunge(with = redact_first_char)]
last_name: String,
#[expunge(with = sha256::digest)]
password: String,
}
#[test]
fn field_with() {
let user = User {
username: "some_user_123".to_string(),
first_name: "Jane".to_string(),
last_name: "Doe".to_string(),
password: "password123".to_string(),
};
assert_eq!(User{
username: "".to_string(),
first_name: "4".to_string(),
last_name: "*oe".to_string(),
password: "ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f".to_string(),
}, user.expunge());
}
skip
Skips a field. Fields marked skip
will be left as-is. This is useful when:
- You want to preserve fields within a struct that are not sensitive
- The type cannot be expunged in a meaningful way
use expunge::Expunge;
#[derive(Expunge)]
struct UserLogin {
username: String,
password: String,
#[expunge(skip)]
last_logged_in_at: i64, // the last login timestamp will be left as-is
}
#[test]
fn skip() {
let login = UserLogin{
username: "gamer100".to_string(),
password: "somepassword123".to_string(),
last_logged_in_at: 1716113380,
};
let expunged = login.expunge();
assert_eq!("", expunged.username);
assert_eq!("", expunged.password);
assert_eq!(1716113380, expunged.last_logged_in_at);
}
zeroize
Zeroize memory for extra security via the secrecy & zeroize crates.
Example:
use expunge::Expunge;
#[derive(Expunge)]
struct UserLogin {
username: String,
#[expunge(as = "<redacted>".to_string(), zeroize)]
password: String, // password will be scrubbed from memory after expunging
}