Skip to main content

kyu_delta/
node_key.rs

1use smol_str::SmolStr;
2
3/// A stable, user-defined identifier for a node.
4///
5/// Unlike `InternalId` (storage-internal, may change across compaction),
6/// a `NodeKey` is the external handle that ingestion pipelines and agents
7/// use to refer to entities.
8#[derive(Clone, Debug, PartialEq, Eq, Hash)]
9pub struct NodeKey {
10    /// The node table (label) this key belongs to.
11    pub label: SmolStr,
12    /// The primary key value as a string.
13    pub primary_key: SmolStr,
14}
15
16impl NodeKey {
17    pub fn new(label: impl Into<SmolStr>, primary_key: impl Into<SmolStr>) -> Self {
18        Self {
19            label: label.into(),
20            primary_key: primary_key.into(),
21        }
22    }
23}
24
25impl std::fmt::Display for NodeKey {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "{}:{}", self.label, self.primary_key)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn new_basic() {
37        let key = NodeKey::new("Function", "main");
38        assert_eq!(key.label, "Function");
39        assert_eq!(key.primary_key, "main");
40    }
41
42    #[test]
43    fn display_format() {
44        let key = NodeKey::new("Document", "invoice_123");
45        assert_eq!(format!("{key}"), "Document:invoice_123");
46    }
47
48    #[test]
49    fn equality() {
50        let a = NodeKey::new("Function", "main");
51        let b = NodeKey::new("Function", "main");
52        assert_eq!(a, b);
53    }
54
55    #[test]
56    fn different_labels_not_equal() {
57        let a = NodeKey::new("Function", "main");
58        let b = NodeKey::new("File", "main");
59        assert_ne!(a, b);
60    }
61
62    #[test]
63    fn hash_consistency() {
64        use std::collections::hash_map::DefaultHasher;
65        use std::hash::{Hash, Hasher};
66        let a = NodeKey::new("X", "y");
67        let b = NodeKey::new("X", "y");
68        let mut ha = DefaultHasher::new();
69        let mut hb = DefaultHasher::new();
70        a.hash(&mut ha);
71        b.hash(&mut hb);
72        assert_eq!(ha.finish(), hb.finish());
73    }
74
75    #[test]
76    fn clone() {
77        let a = NodeKey::new("A", "b");
78        let b = a.clone();
79        assert_eq!(a, b);
80    }
81}