vortex_session/
registry.rs1use std::cmp::Ordering;
8use std::fmt;
9use std::fmt::Debug;
10use std::fmt::Display;
11use std::fmt::Formatter;
12use std::hash::Hash;
13use std::ops::Deref;
14use std::sync::Arc;
15use std::sync::LazyLock;
16use std::sync::OnceLock;
17
18use lasso::Spur;
19use lasso::ThreadedRodeo;
20use parking_lot::RwLock;
21use vortex_error::VortexExpect;
22use vortex_utils::aliases::dash_map::DashMap;
23
24static INTERNER: LazyLock<ThreadedRodeo> = LazyLock::new(ThreadedRodeo::new);
26
27#[derive(Clone, Copy, PartialEq, Eq, Hash)]
33pub struct Id(Spur);
34
35impl Id {
36 pub fn new(s: &str) -> Self {
38 Self(INTERNER.get_or_intern(s))
39 }
40
41 pub fn new_static(s: &'static str) -> Self {
43 Self(INTERNER.get_or_intern_static(s))
44 }
45
46 pub fn as_str(&self) -> &str {
48 let s = INTERNER.resolve(&self.0);
49 unsafe { &*(s as *const str) }
52 }
53}
54
55impl From<&str> for Id {
56 fn from(s: &str) -> Self {
57 Self::new(s)
58 }
59}
60
61impl Display for Id {
62 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63 f.write_str(self.as_str())
64 }
65}
66
67impl Debug for Id {
68 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69 write!(f, "Id(\"{}\")", self.as_str())
70 }
71}
72
73impl PartialOrd for Id {
74 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
75 Some(self.cmp(other))
76 }
77}
78
79impl Ord for Id {
80 fn cmp(&self, other: &Self) -> Ordering {
81 self.as_str().cmp(other.as_str())
82 }
83}
84
85impl AsRef<str> for Id {
86 fn as_ref(&self) -> &str {
87 self.as_str()
88 }
89}
90
91impl PartialEq<&Id> for Id {
92 fn eq(&self, other: &&Id) -> bool {
93 self == *other
94 }
95}
96
97impl PartialEq<Id> for &Id {
98 fn eq(&self, other: &Id) -> bool {
99 *self == other
100 }
101}
102
103pub struct CachedId {
120 s: &'static str,
121 cached: OnceLock<Id>,
122}
123
124impl CachedId {
125 pub const fn new(s: &'static str) -> Self {
127 Self {
128 s,
129 cached: OnceLock::new(),
130 }
131 }
132}
133
134impl Deref for CachedId {
135 type Target = Id;
136
137 fn deref(&self) -> &Id {
138 self.cached.get_or_init(|| Id::new(self.s))
139 }
140}
141
142#[derive(Clone, Debug)]
144pub struct Registry<T>(Arc<DashMap<Id, T>>);
145
146impl<T> Default for Registry<T> {
147 fn default() -> Self {
148 Self(Default::default())
149 }
150}
151
152impl<T: Clone> Registry<T> {
153 pub fn empty() -> Self {
154 Self(Default::default())
155 }
156
157 pub fn ids(&self) -> impl Iterator<Item = Id> + '_ {
159 self.0.iter().map(|i| *i.key())
160 }
161
162 pub fn items(&self) -> impl Iterator<Item = T> + '_ {
164 self.0.iter().map(|i| i.value().clone())
165 }
166
167 pub fn find_many<'a>(
169 &self,
170 ids: impl IntoIterator<Item = &'a Id>,
171 ) -> impl Iterator<Item = Option<impl Deref<Target = T>>> {
172 ids.into_iter().map(|id| self.0.get(id))
173 }
174
175 pub fn find(&self, id: &Id) -> Option<T> {
177 self.0.get(id).as_deref().cloned()
178 }
179
180 pub fn register(&self, id: impl Into<Id>, item: impl Into<T>) {
182 self.0.insert(id.into(), item.into());
183 }
184
185 pub fn with(self, id: impl Into<Id>, item: impl Into<T>) -> Self {
187 self.register(id, item.into());
188 self
189 }
190}
191
192#[derive(Clone, Debug)]
195pub struct ReadContext {
196 ids: Arc<[Id]>,
197}
198
199impl ReadContext {
200 pub fn new(ids: impl Into<Arc<[Id]>>) -> Self {
202 Self { ids: ids.into() }
203 }
204
205 pub fn resolve(&self, idx: u16) -> Option<Id> {
207 self.ids.get(idx as usize).cloned()
208 }
209
210 pub fn ids(&self) -> &[Id] {
211 &self.ids
212 }
213}
214
215#[derive(Clone, Debug)]
225pub struct Context<T> {
226 ids: Arc<RwLock<Vec<Id>>>,
230 registry: Option<Registry<T>>,
232}
233
234impl<T> Default for Context<T> {
235 fn default() -> Self {
236 Self {
237 ids: Arc::new(RwLock::new(Vec::new())),
238 registry: None,
239 }
240 }
241}
242
243impl<T: Clone> Context<T> {
244 pub fn new(ids: Vec<Id>) -> Self {
246 Self {
247 ids: Arc::new(RwLock::new(ids)),
248 registry: None,
249 }
250 }
251
252 pub fn empty() -> Self {
254 Self::default()
255 }
256
257 pub fn with_registry(mut self, registry: Registry<T>) -> Self {
259 self.registry = Some(registry);
260 self
261 }
262
263 pub fn intern(&self, id: &Id) -> Option<u16> {
265 if let Some(registry) = &self.registry
266 && registry.find(id).is_none()
267 {
268 return None;
270 }
271
272 let mut ids = self.ids.write();
273 if let Some(idx) = ids.iter().position(|e| e == id) {
274 return Some(u16::try_from(idx).vortex_expect("Cannot have more than u16::MAX items"));
275 }
276
277 let idx = ids.len();
278 assert!(
279 idx < u16::MAX as usize,
280 "Cannot have more than u16::MAX items"
281 );
282 ids.push(*id);
283 Some(u16::try_from(idx).vortex_expect("checked already"))
284 }
285
286 pub fn to_ids(&self) -> Vec<Id> {
288 self.ids.read().clone()
289 }
290}