use gaze_types::{PiiClass, SafetyNetError, SafetyNetPiiClass};
const MAX_KIJI_LABEL_LEN: usize = 16;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum KijiLabel {
Person,
Location,
Organization,
Miscellaneous,
}
impl KijiLabel {
pub fn as_str(self) -> &'static str {
match self {
Self::Person => "person",
Self::Location => "location",
Self::Organization => "organization",
Self::Miscellaneous => "miscellaneous",
}
}
}
pub fn validate_kiji_label(label: &str) -> Result<(), SafetyNetError> {
if label.is_empty() || label.len() > MAX_KIJI_LABEL_LEN {
return Err(invalid_label());
}
if label
.bytes()
.all(|byte| byte.is_ascii_lowercase() || byte == b'_')
{
Ok(())
} else {
Err(invalid_label())
}
}
pub fn map_kiji_label(label: &str) -> Result<KijiLabel, SafetyNetError> {
validate_kiji_label(label)?;
match label {
"person" => Ok(KijiLabel::Person),
"location" => Ok(KijiLabel::Location),
"organization" => Ok(KijiLabel::Organization),
"miscellaneous" => Ok(KijiLabel::Miscellaneous),
_ => Err(SafetyNetError::InvalidOutput {
message: "kiji returned unsupported label".to_string(),
}),
}
}
pub fn kiji_label_to_safety_net_class(label: KijiLabel) -> SafetyNetPiiClass {
match label {
KijiLabel::Person => SafetyNetPiiClass::Name,
KijiLabel::Location => SafetyNetPiiClass::Location,
KijiLabel::Organization | KijiLabel::Miscellaneous => SafetyNetPiiClass::Name,
}
}
pub fn kiji_label_to_pii_class(label: KijiLabel) -> PiiClass {
kiji_label_to_safety_net_class(label).to_pii_class()
}
fn invalid_label() -> SafetyNetError {
SafetyNetError::InvalidOutput {
message: "kiji returned invalid label".to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn official_labels_map_to_closed_classes() {
let cases = [
("person", PiiClass::Name),
("location", PiiClass::Location),
("organization", PiiClass::Name),
("miscellaneous", PiiClass::Name),
];
for (label, expected) in cases {
let kiji_label = map_kiji_label(label).expect("official label");
assert_eq!(kiji_label.as_str(), label);
assert_eq!(kiji_label_to_pii_class(kiji_label), expected);
}
}
#[test]
fn unknown_and_invalid_labels_fail_closed() {
assert!(map_kiji_label("PERSON").is_err());
assert!(map_kiji_label("per-son").is_err());
assert!(map_kiji_label("date").is_err());
assert!(map_kiji_label("").is_err());
assert!(map_kiji_label("organization_12345").is_err());
}
}