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