turtle_build/
path_pool.rs1use alloc::sync::Arc;
2use scc::HashSet;
3
4#[derive(Debug, Default)]
6pub struct PathPool {
7 paths: HashSet<Arc<str>>,
8}
9
10impl PathPool {
11 pub fn new() -> Self {
13 Self::default()
14 }
15
16 pub fn intern(&self, path: &str) -> Arc<str> {
18 self.paths.read_sync(path, Clone::clone).unwrap_or_else(|| {
19 let _ = self.paths.insert_sync(path.into());
21
22 self.intern(path)
23 })
24 }
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30 use pretty_assertions::assert_eq;
31
32 #[test]
33 fn intern_path() {
34 assert_eq!(PathPool::new().intern("foo"), "foo".into());
35 }
36
37 #[test]
38 fn intern_same_path_twice() {
39 let pool = PathPool::new();
40
41 assert!(Arc::ptr_eq(&pool.intern("foo"), &pool.intern("foo")));
42 }
43
44 #[test]
45 fn intern_different_paths() {
46 let pool = PathPool::new();
47
48 assert_eq!(pool.intern("foo"), "foo".into());
49 assert_eq!(pool.intern("bar"), "bar".into());
50 }
51
52 #[test]
53 fn intern_same_path_after_different_path() {
54 let pool = PathPool::new();
55 let path = pool.intern("foo");
56
57 pool.intern("bar");
58
59 assert!(Arc::ptr_eq(&path, &pool.intern("foo")));
60 }
61}