diff-priv 0.1.0

k-anonymity, (c,l)-diversity and ε-differential privacy framework
Documentation
use std::time::{SystemTime, UNIX_EPOCH};

use bimap::BiMap;
use uuid::Uuid;

use crate::data_manipulation::anonymizable::{
    Anonymizable, QuasiIdentifierType, QuasiIdentifierTypes, SensitiveAttribute,
};

lazy_static! {
    static ref CLASS_BIMAP: BiMap<&'static str, i32> =
        BiMap::from_iter(vec![("<=50K", 0), (">50K", 1),]);
}

#[derive(Debug, Serialize, Clone, Deserialize)]
pub struct Adult {
    timestamp: i32,
    age: i32,
    fnlwgt: i32,
    education_num: i32,
    capital_gain: i32,
    capital_loss: i32,
    hours_per_week: i32,
    class: String,
    #[serde(skip_deserializing, default = "default_time")]
    time_generated: SystemTime,
}

fn default_time() -> SystemTime {
    SystemTime::now()
}

impl Default for Adult {
    fn default() -> Self {
        Self {
            timestamp: 0,
            age: 0,
            fnlwgt: 0,
            education_num: 0,
            capital_gain: 0,
            capital_loss: 0,
            hours_per_week: 0,
            class: "".to_string(),
            time_generated: SystemTime::now(),
        }
    }
}

impl Adult {
    fn get_age_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.age),
            QuasiIdentifierType::Integer(1),
            QuasiIdentifierType::Integer(100),
            1,
        ))
    }

    fn get_fnlwgt_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.fnlwgt),
            QuasiIdentifierType::Integer(1),
            QuasiIdentifierType::Integer(1500000),
            1,
        ))
    }

    fn get_education_num_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.education_num),
            QuasiIdentifierType::Integer(1),
            QuasiIdentifierType::Integer(20),
            1,
        ))
    }

    fn get_capital_gain_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.capital_gain),
            QuasiIdentifierType::Integer(0),
            QuasiIdentifierType::Integer(100000),
            1,
        ))
    }

    fn get_capital_loss_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.capital_loss),
            QuasiIdentifierType::Integer(0),
            QuasiIdentifierType::Integer(5000),
            1,
        ))
    }

    fn get_hours_per_week_qi(&self) -> QuasiIdentifierTypes {
        QuasiIdentifierTypes::Interval((
            QuasiIdentifierType::Integer(self.hours_per_week),
            QuasiIdentifierType::Integer(1),
            QuasiIdentifierType::Integer(100),
            1,
        ))
    }
}

impl Anonymizable for Adult {
    fn quasi_identifiers(&self) -> Vec<QuasiIdentifierTypes> {
        let age = self.get_age_qi();
        let fnlwgt = self.get_fnlwgt_qi();
        let education_num = self.get_education_num_qi();
        let capital_gain = self.get_capital_gain_qi();
        let capital_loss = self.get_capital_loss_qi();
        let hours_per_week = self.get_hours_per_week_qi();

        vec![
            age,
            fnlwgt,
            education_num,
            capital_gain,
            capital_loss,
            hours_per_week,
        ]
    }

    fn update_quasi_identifiers(&self, mut qi: Vec<QuasiIdentifierTypes>) -> Self {
        if let (
            QuasiIdentifierType::Integer(hours_per_week),
            QuasiIdentifierType::Integer(capital_loss),
            QuasiIdentifierType::Integer(capital_gain),
            QuasiIdentifierType::Integer(education_num),
            QuasiIdentifierType::Integer(fnlwgt),
            QuasiIdentifierType::Integer(age),
        ) = (
            qi.pop().unwrap().extract_value(),
            qi.pop().unwrap().extract_value(),
            qi.pop().unwrap().extract_value(),
            qi.pop().unwrap().extract_value(),
            qi.pop().unwrap().extract_value(),
            qi.pop().unwrap().extract_value(),
        ) {
            Self {
                timestamp: self.timestamp,
                age,
                fnlwgt,
                education_num,
                capital_gain,
                capital_loss,
                hours_per_week,
                class: self.class.to_owned(),
                time_generated: self.time_generated,
            }
        } else {
            panic!("Couldn't Adult with QI's")
        }
    }

    fn sensitive_value(&self) -> SensitiveAttribute {
        SensitiveAttribute::String(self.class.to_owned())
    }

    fn extract_string_values(&self, uuid: Uuid, dr: f64) -> Vec<String> {
        vec![
            uuid.to_string(),
            dr.to_string(),
            self.timestamp.to_string(),
            self.age.to_string(),
            self.fnlwgt.to_string(),
            self.education_num.to_string(),
            self.capital_gain.to_string(),
            self.capital_loss.to_string(),
            self.hours_per_week.to_string(),
            self.class.to_owned(),
        ]
    }

    fn get_timestamp(&self) -> SystemTime {
        self.time_generated
    }
}