device_driver_common/
interner.rs1use std::{
4 borrow::Borrow,
5 collections::HashMap,
6 hash::Hash,
7 mem,
8 num::NonZero,
9 ops::Deref,
10 sync::{LazyLock, Mutex},
11};
12
13static GLOBAL_INTERNER: LazyLock<Mutex<Interner>> =
14 LazyLock::new(|| Mutex::new(Interner::with_capacity(1024 * 32)));
15
16pub struct Interner {
17 map: HashMap<&'static str, NonZero<u32>>,
18 vec: Vec<&'static str>,
19 buf: String,
20 full: Vec<String>,
21}
22
23impl Interner {
24 fn with_capacity(cap: usize) -> Interner {
25 let cap = cap.next_power_of_two();
26 let mut interner = Interner {
27 map: HashMap::default(),
28 vec: Vec::new(),
29 buf: String::with_capacity(cap),
30 full: Vec::new(),
31 };
32
33 let default_istr = interner.intern("");
35 debug_assert_eq!(default_istr.0.get(), 1);
36
37 interner
38 }
39
40 pub fn intern(&mut self, name: &str) -> Istr {
41 if let Some(&id) = self.map.get(name) {
42 return Istr(id);
43 }
44 let name = unsafe { self.alloc(name) };
45 let id = NonZero::new(self.map.len() as u32 + 1).unwrap();
46 self.map.insert(name, id);
47 self.vec.push(name);
48
49 debug_assert!(self.lookup(Istr(id)) == name);
50 debug_assert!(self.intern(name) == Istr(id));
51
52 Istr(id)
53 }
54
55 pub fn lookup(&self, id: Istr) -> &'static str {
56 self.vec[id.0.get() as usize - 1]
57 }
58
59 unsafe fn alloc(&mut self, name: &str) -> &'static str {
60 let cap = self.buf.capacity();
61 if cap < self.buf.len() + name.len() {
62 let new_cap = (cap.max(name.len()) + 1).next_power_of_two();
63 let new_buf = String::with_capacity(new_cap);
64 let old_buf = mem::replace(&mut self.buf, new_buf);
65 self.full.push(old_buf);
66 }
67
68 let interned = {
69 let start = self.buf.len();
70 self.buf.push_str(name);
71 &self.buf[start..]
72 };
73
74 unsafe { &*(interned as *const str) }
75 }
76}
77
78impl Drop for Interner {
79 fn drop(&mut self) {
80 panic!("Interner must not be dropped since it has given out static references")
81 }
82}
83
84#[derive(PartialEq, Eq, Clone, Copy)]
85pub struct Istr(NonZero<u32>);
86
87impl Istr {
88 pub fn as_str(self) -> &'static str {
89 let interner = GLOBAL_INTERNER.lock().unwrap();
90 interner.lookup(self)
91 }
92}
93
94impl std::fmt::Debug for Istr {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 if f.alternate() {
97 write!(f, "({}){:?}", self.0, self.as_str())
98 } else {
99 write!(f, "{:?}", self.as_str())
100 }
101 }
102}
103
104impl std::fmt::Display for Istr {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "{}", self.as_str())
107 }
108}
109
110impl Deref for Istr {
111 type Target = str;
112
113 fn deref(&self) -> &Self::Target {
114 self.as_str()
115 }
116}
117
118impl AsRef<str> for Istr {
119 fn as_ref(&self) -> &str {
120 self.as_str()
121 }
122}
123
124impl Borrow<str> for Istr {
125 fn borrow(&self) -> &str {
126 self.as_str()
127 }
128}
129
130impl Hash for Istr {
131 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
132 self.as_str().hash(state);
133 }
134}
135
136impl<'a> From<&'a str> for Istr {
137 fn from(value: &'a str) -> Self {
138 value.intern()
139 }
140}
141
142impl Default for Istr {
143 fn default() -> Self {
144 Self(NonZero::new(1).unwrap())
145 }
146}
147
148pub trait StrExt {
149 fn intern(&self) -> Istr;
150}
151impl<T: AsRef<str>> StrExt for T {
152 fn intern(&self) -> Istr {
153 GLOBAL_INTERNER.lock().unwrap().intern(self.as_ref())
154 }
155}