Skip to main content

kcl_lib/execution/
id_generator.rs

1//! A generator for ArtifactIds that can be stable across executions.
2
3use crate::execution::ArtifactId;
4use crate::execution::ModuleId;
5
6const NAMESPACE_KCL: uuid::Uuid = uuid::uuid!("8bda3118-75eb-58c7-a866-bef1dcb495e7");
7
8/// A generator for ArtifactIds that can be stable across executions.
9#[derive(Debug, Clone, Default, PartialEq)]
10pub struct IdGenerator {
11    module_id: Option<ModuleId>,
12    next_id: u64,
13}
14
15impl IdGenerator {
16    pub fn new(module_id: Option<ModuleId>) -> Self {
17        Self { module_id, next_id: 0 }
18    }
19
20    pub fn next_uuid(&mut self) -> uuid::Uuid {
21        let next_id = self.next_id;
22
23        let next = format!(
24            "{} {}",
25            self.module_id.map(|id| id.to_string()).unwrap_or("none".to_string()),
26            next_id
27        );
28        let next_uuid = uuid::Uuid::new_v5(&NAMESPACE_KCL, next.as_bytes());
29
30        self.next_id += 1;
31
32        next_uuid
33    }
34
35    pub fn next_artifact_id(&mut self) -> ArtifactId {
36        ArtifactId::new(self.next_uuid())
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_id_generator() {
46        let mut generator = IdGenerator::new(Some(ModuleId::default()));
47
48        let uuid1 = generator.next_uuid();
49        let uuid2 = generator.next_uuid();
50
51        assert_ne!(uuid1, uuid2);
52    }
53
54    #[test]
55    // Test that the same generator produces the same UUIDs.
56    fn test_id_generator_stable() {
57        let mut generator = IdGenerator::new(Some(ModuleId::default()));
58
59        let uuid1 = generator.next_uuid();
60        let uuid2 = generator.next_uuid();
61
62        let mut generator = IdGenerator::new(Some(ModuleId::default()));
63
64        let uuid3 = generator.next_uuid();
65        let uuid4 = generator.next_uuid();
66
67        assert_eq!(uuid1, uuid3);
68        assert_eq!(uuid2, uuid4);
69    }
70
71    #[test]
72    // Generate 20 uuids and make sure all are unique.
73    fn test_id_generator_unique() {
74        let mut generator = IdGenerator::new(Some(ModuleId::default()));
75
76        let mut uuids = Vec::new();
77
78        for _ in 0..20 {
79            uuids.push(generator.next_uuid());
80        }
81
82        for i in 0..uuids.len() {
83            for j in i + 1..uuids.len() {
84                assert_ne!(uuids[i], uuids[j]);
85            }
86        }
87    }
88}