linkrs_query/executor/streaming/
interner.rs1use dashmap::DashMap;
2use std::sync::Arc;
3
4#[derive(Clone)]
5pub struct StrInterner {
6 inner: Arc<DashMap<String, Arc<str>>>,
7}
8
9impl StrInterner {
10 pub fn new() -> Self {
11 Self {
12 inner: Arc::new(DashMap::new()),
13 }
14 }
15
16 pub fn with_capacity(capacity: usize) -> Self {
17 Self {
18 inner: Arc::new(DashMap::with_capacity(capacity)),
19 }
20 }
21
22 pub fn intern(&self, s: &str) -> Arc<str> {
23 if let Some(entry) = self.inner.get(s) {
24 return Arc::clone(&entry);
25 }
26 let interned: Arc<str> = Arc::from(s);
27 self.inner
28 .insert(interned.to_string(), Arc::clone(&interned));
29 interned
30 }
31
32 pub fn intern_string(&self, s: String) -> Arc<str> {
33 if let Some(entry) = self.inner.get(s.as_str()) {
34 return Arc::clone(&entry);
35 }
36 let interned: Arc<str> = Arc::from(s);
37 self.inner
38 .insert(interned.to_string(), Arc::clone(&interned));
39 interned
40 }
41
42 pub fn len(&self) -> usize {
43 self.inner.len()
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.inner.is_empty()
48 }
49
50 pub fn clear(&self) {
51 self.inner.clear();
52 }
53}
54
55impl Default for StrInterner {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_intern_basic() {
67 let interner = StrInterner::new();
68 let a = interner.intern("hello world");
69 let b = interner.intern("hello world");
70 assert!(Arc::ptr_eq(&a, &b));
71 }
72
73 #[test]
74 fn test_intern_distinct() {
75 let interner = StrInterner::new();
76 let a = interner.intern("hello");
77 let b = interner.intern("world");
78 assert!(!Arc::ptr_eq(&a, &b));
79 }
80
81 #[test]
82 fn test_intern_string() {
83 let interner = StrInterner::new();
84 let s = String::from("test string");
85 let a = interner.intern_string(s);
86 let b = interner.intern("test string");
87 assert!(Arc::ptr_eq(&a, &b));
88 }
89}