polydat_core/kernel/
intern.rs1use std::sync::RwLock;
13
14pub struct StaticInterner;
16
17struct StaticTable {
18 entries: Vec<&'static str>,
19 index: std::collections::HashMap<&'static str, u32>,
20}
21
22static STATIC_STRINGS: RwLock<Option<StaticTable>> = RwLock::new(None);
23
24impl StaticInterner {
25 pub fn intern(s: &str) -> &'static str {
27 let found: Option<&'static str> = STATIC_STRINGS
30 .read()
31 .unwrap()
32 .as_ref()
33 .and_then(|t| t.index.get(s).map(|&id| t.entries[id as usize]));
34 if let Some(text) = found {
35 return text;
36 }
37 let mut guard = STATIC_STRINGS.write().unwrap();
38 let table = guard.get_or_insert_with(|| StaticTable {
39 entries: Vec::new(),
40 index: std::collections::HashMap::new(),
41 });
42 if let Some(&id) = table.index.get(s) {
43 return table.entries[id as usize];
44 }
45 let leaked: &'static str = Box::leak(s.to_string().into_boxed_str());
46 let id = table.entries.len() as u32;
47 table.entries.push(leaked);
48 table.index.insert(leaked, id);
49 leaked
50 }
51
52 pub fn resolve(id: u32) -> &'static str {
54 STATIC_STRINGS
55 .read()
56 .unwrap()
57 .as_ref()
58 .and_then(|t| t.entries.get(id as usize).copied())
59 .unwrap_or("")
60 }
61
62 pub fn len() -> usize {
64 STATIC_STRINGS
65 .read()
66 .unwrap()
67 .as_ref()
68 .map_or(0, |t| t.entries.len())
69 }
70}
71
72#[inline]
75pub fn static_pair(s: &'static str) -> (u64, u64) {
76 (s.as_ptr() as usize as u64, s.len() as u64)
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn interning_dedups_and_keeps_bytes_in_place() {
85 let a = StaticInterner::intern("intern-test-constant");
86 let b = StaticInterner::intern("intern-test-constant");
87 assert_eq!(
88 a.as_ptr(),
89 b.as_ptr(),
90 "the same text interns to the same bytes"
91 );
92 assert_eq!(a, "intern-test-constant");
93 let (p, l) = static_pair(a);
94 assert_eq!(p, a.as_ptr() as usize as u64);
95 assert_eq!(l, a.len() as u64);
96 }
97}