maskify 0.1.0

Zero-dependency, blazing-fast Rust crate for masking sensitive data — emails, phones, cards, Aadhaar, PAN, IPs & more. Comes with trait extensions and a builder pattern.
Documentation
use maskify::*;

// =================== EMAIL ===================

#[test]
fn email_normal() {
    assert_eq!(mask_email("user@example.com"), "u***@example.com");
}

#[test]
fn email_short_local_2() {
    assert_eq!(mask_email("ab@test.com"), "a*@test.com");
}

#[test]
fn email_short_local_1() {
    assert_eq!(mask_email("a@test.com"), "*@test.com");
}

#[test]
fn email_long_local() {
    assert_eq!(mask_email("longusername@gmail.com"), "l****@gmail.com");
}

#[test]
fn email_empty() {
    assert_eq!(mask_email(""), "");
}

#[test]
fn email_no_at() {
    assert_eq!(mask_email("invalid"), "*******");
}

// =================== PHONE ===================

#[test]
fn phone_10_digits() {
    assert_eq!(mask_phone("9876543210"), "98******10");
}

#[test]
fn phone_with_country_code() {
    assert_eq!(mask_phone("+91-9876543210"), "91********10");
}

#[test]
fn phone_short() {
    assert_eq!(mask_phone("123"), "***");
}

#[test]
fn phone_5_digits() {
    assert_eq!(mask_phone("12345"), "12*45");
}

#[test]
fn phone_empty() {
    assert_eq!(mask_phone(""), "");
}

// =================== CARD ===================

#[test]
fn card_16_digits() {
    assert_eq!(mask_card("4111111111111111"), "4111********1111");
}

#[test]
fn card_with_dashes() {
    assert_eq!(mask_card("4111-1111-1111-1111"), "4111********1111");
}

#[test]
fn card_short() {
    assert_eq!(mask_card("1234"), "****");
}

#[test]
fn card_empty() {
    assert_eq!(mask_card(""), "");
}

// =================== NAME ===================

#[test]
fn name_two_words() {
    assert_eq!(mask_name("John Doe"), "J*** D**");
}

#[test]
fn name_three_words() {
    assert_eq!(mask_name("Alice Bob Charlie"), "A**** B** C******");
}

#[test]
fn name_single_char() {
    assert_eq!(mask_name("A"), "A");
}

#[test]
fn name_empty() {
    assert_eq!(mask_name(""), "");
}

// =================== IP ===================

#[test]
fn ip_v4_normal() {
    assert_eq!(mask_ip("192.168.1.100"), "192.*.*.*");
}

#[test]
fn ip_v4_short() {
    assert_eq!(mask_ip("10.0.0.1"), "10.*.*.*");
}

#[test]
fn ip_empty() {
    assert_eq!(mask_ip(""), "");
}

// =================== AADHAAR ===================

#[test]
fn aadhaar_plain() {
    assert_eq!(mask_aadhaar("123456789012"), "XXXX-XXXX-9012");
}

#[test]
fn aadhaar_with_spaces() {
    assert_eq!(mask_aadhaar("1234 5678 9012"), "XXXX-XXXX-9012");
}

#[test]
fn aadhaar_invalid() {
    assert_eq!(mask_aadhaar("12345"), "*****");
}

// =================== PAN ===================

#[test]
fn pan_valid() {
    assert_eq!(mask_pan("ABCDE1234F"), "A********F");
}

#[test]
fn pan_invalid() {
    assert_eq!(mask_pan("SHORT"), "*****");
}

// =================== CUSTOM ===================

#[test]
fn custom_hash() {
    assert_eq!(mask_custom("HelloWorld", 2, 2, '#'), "He######ld");
}

#[test]
fn custom_too_short() {
    assert_eq!(mask_custom("Hi", 1, 1, '*'), "Hi");
}

#[test]
fn custom_empty() {
    assert_eq!(mask_custom("", 1, 1, '*'), "");
}

#[test]
fn custom_no_end() {
    assert_eq!(mask_custom("Hello", 1, 0, '*'), "H****");
}

// =================== MASK ALL ===================

#[test]
fn all_normal() {
    assert_eq!(mask_all("secret"), "******");
}

#[test]
fn all_empty() {
    assert_eq!(mask_all(""), "");
}

// =================== TRAIT ===================

#[test]
fn trait_str_email() {
    assert_eq!("user@example.com".mask_email(), "u***@example.com");
}

#[test]
fn trait_str_phone() {
    assert_eq!("9876543210".mask_phone(), "98******10");
}

#[test]
fn trait_string_email() {
    let email = String::from("test@gmail.com");
    assert_eq!(email.mask_email(), "t***@gmail.com");
}

#[test]
fn trait_string_phone() {
    let phone = String::from("9876543210");
    assert_eq!(phone.mask_phone(), "98******10");
}

// =================== BUILDER ===================

#[test]
fn builder_basic() {
    let masker = Masker::new()
        .keep_start(2)
        .keep_end(3)
        .mask_char('#');

    assert_eq!(masker.apply("HelloWorld"), "He#####rld");
}

#[test]
fn builder_reuse() {
    let masker = Masker::new().keep_start(4).keep_end(4);

    assert_eq!(masker.apply("1234567890123456"), "1234********3456");
    assert_eq!(masker.apply("ABCDEFGHIJKLMNOP"), "ABCD********MNOP");
}

#[test]
fn builder_default() {
    let masker = Masker::default();
    assert_eq!(masker.apply("secret"), "******");
}