Skip to main content

zer_blocking/keys/
exact.rs

1use zer_core::{record::Record, schema::Schema};
2
3use crate::normalize::normalize_text;
4use super::BlockingKey;
5
6pub struct ExactFieldKey {
7    field: String,
8}
9
10impl ExactFieldKey {
11    pub fn new(field: &str) -> Self {
12        Self { field: field.into() }
13    }
14}
15
16impl BlockingKey for ExactFieldKey {
17    fn name(&self) -> &str {
18        "exact"
19    }
20
21    fn extract(&self, record: &Record, _schema: &Schema) -> Vec<String> {
22        let cow = record.field_as_str(&self.field);
23        let raw = match cow.as_deref() {
24            Some(s) => s,
25            None    => return vec![],
26        };
27
28        let normalized = normalize_text(raw);
29        if normalized.is_empty() {
30            return vec![];
31        }
32
33        vec![normalized]
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use zer_core::{record::FieldValue, schema::{SchemaBuilder, FieldKind}};
41
42    fn schema() -> Schema {
43        SchemaBuilder::new().field("category", FieldKind::Categorical).build().unwrap()
44    }
45
46    #[test]
47    fn exact_normalizes_and_matches() {
48        let k  = ExactFieldKey::new("category");
49        let s  = schema();
50        let r1 = Record::new(1).insert("category", FieldValue::Text("Eenmanszaak".into()));
51        let r2 = Record::new(2).insert("category", FieldValue::Text("EENMANSZAAK".into()));
52        assert_eq!(k.extract(&r1, &s), k.extract(&r2, &s));
53    }
54
55    #[test]
56    fn exact_empty_field_returns_empty() {
57        let k = ExactFieldKey::new("category");
58        let r = Record::new(1).insert("category", FieldValue::Text("".into()));
59        assert!(k.extract(&r, &schema()).is_empty());
60    }
61
62    #[test]
63    fn exact_missing_field_returns_empty() {
64        let k = ExactFieldKey::new("category");
65        let r = Record::new(1);
66        assert!(k.extract(&r, &schema()).is_empty());
67    }
68}