1use super::Sysno;
2use crate::SysnoSet;
3use crate::set::SysnoSetIter;
4use core::fmt;
5use core::mem::MaybeUninit;
6
7type DataArray<T> = [MaybeUninit<T>; Sysno::table_size()];
8
9pub struct SysnoMap<T> {
62 is_set: SysnoSet,
63 data: DataArray<T>,
64}
65
66#[inline]
68const fn get_idx(sysno: Sysno) -> usize {
69 (sysno.id() as usize) - (Sysno::first().id() as usize)
70}
71
72impl<T> Default for SysnoMap<T> {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78impl<T> SysnoMap<T> {
79 pub const fn new() -> Self {
81 Self {
82 is_set: SysnoSet::empty(),
83 data: unsafe { MaybeUninit::uninit().assume_init() },
84 }
85 }
86
87 pub const fn contains_key(&self, sysno: Sysno) -> bool {
89 self.is_set.contains(sysno)
90 }
91
92 pub fn clear(&mut self) {
94 for sysno in &self.is_set {
95 unsafe { self.data[get_idx(sysno)].assume_init_drop() }
96 }
97 self.is_set.clear();
98 }
99
100 pub fn is_empty(&self) -> bool {
105 self.is_set.is_empty()
106 }
107
108 pub fn count(&self) -> usize {
113 self.is_set.count()
114 }
115
116 pub fn insert(&mut self, sysno: Sysno, value: T) -> Option<T> {
119 let uninit = &mut self.data[get_idx(sysno)];
120 if self.is_set.insert(sysno) {
121 uninit.write(value);
123 None
124 } else {
125 let old = core::mem::replace(uninit, MaybeUninit::new(value));
127 Some(unsafe { old.assume_init() })
128 }
129 }
130
131 pub fn remove(&mut self, sysno: Sysno) -> Option<T> {
134 if self.is_set.remove(sysno) {
135 let old = core::mem::replace(
136 &mut self.data[get_idx(sysno)],
137 MaybeUninit::uninit(),
138 );
139 Some(unsafe { old.assume_init() })
140 } else {
141 None
142 }
143 }
144
145 pub fn get(&self, sysno: Sysno) -> Option<&T> {
148 if self.is_set.contains(sysno) {
149 Some(unsafe { self.data[get_idx(sysno)].assume_init_ref() })
150 } else {
151 None
152 }
153 }
154
155 pub fn get_mut(&mut self, sysno: Sysno) -> Option<&mut T> {
158 if self.is_set.contains(sysno) {
159 Some(unsafe { self.data[get_idx(sysno)].assume_init_mut() })
160 } else {
161 None
162 }
163 }
164
165 pub fn iter(&self) -> SysnoMapIter<'_, T> {
167 SysnoMapIter {
168 iter: self.is_set.iter(),
169 data: &self.data,
170 }
171 }
172
173 pub fn values(&self) -> SysnoMapValues<'_, T> {
176 SysnoMapValues(self.is_set.iter(), &self.data)
177 }
178}
179
180impl<T: Copy> SysnoMap<T> {
181 pub const fn from_slice(slice: &[(Sysno, T)]) -> Self {
205 let mut data: DataArray<T> =
206 unsafe { MaybeUninit::uninit().assume_init() };
207
208 let mut is_set = SysnoSet::empty();
209
210 let mut i = 0;
213 while i < slice.len() {
214 let sysno = slice[i].0;
215 let (idx, mask) = SysnoSet::get_idx_mask(sysno);
216 is_set.data[idx] |= mask;
217 data[get_idx(sysno)] = MaybeUninit::new(slice[i].1);
218 i += 1;
219 }
220
221 Self { is_set, data }
222 }
223}
224
225impl<T: Clone> SysnoMap<T> {
226 pub fn init_all(default: &T) -> Self {
229 SysnoSet::all()
230 .iter()
231 .map(|v| (v, default.clone()))
232 .collect()
233 }
234}
235
236impl<T> Drop for SysnoMap<T> {
237 fn drop(&mut self) {
238 self.clear();
239 }
240}
241
242pub struct SysnoMapIter<'a, T> {
245 iter: SysnoSetIter<'a>,
246 data: &'a DataArray<T>,
247}
248
249impl<'a, T> Iterator for SysnoMapIter<'a, T> {
250 type Item = (Sysno, &'a T);
251
252 fn next(&mut self) -> Option<Self::Item> {
253 self.iter.next().map(|sysno| {
254 let value = unsafe { self.data[get_idx(sysno)].assume_init_ref() };
255 (sysno, value)
256 })
257 }
258}
259
260pub struct SysnoMapValues<'a, T>(SysnoSetIter<'a>, &'a DataArray<T>);
262
263impl<'a, T> Iterator for SysnoMapValues<'a, T> {
264 type Item = &'a T;
265
266 fn next(&mut self) -> Option<Self::Item> {
267 self.0
268 .next()
269 .map(|sysno| unsafe { self.1[get_idx(sysno)].assume_init_ref() })
270 }
271}
272
273impl<T: fmt::Debug> fmt::Debug for SysnoMap<T> {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 f.debug_map().entries(self.iter()).finish()
276 }
277}
278
279impl<T> Extend<(Sysno, T)> for SysnoMap<T> {
280 fn extend<I: IntoIterator<Item = (Sysno, T)>>(&mut self, iter: I) {
281 for (sysno, value) in iter {
282 self.insert(sysno, value);
283 }
284 }
285}
286
287impl<T> FromIterator<(Sysno, T)> for SysnoMap<T> {
288 fn from_iter<I>(iter: I) -> Self
289 where
290 I: IntoIterator<Item = (Sysno, T)>,
291 {
292 let mut map = SysnoMap::new();
293 map.extend(iter);
294 map
295 }
296}
297
298impl<'a, T> IntoIterator for &'a SysnoMap<T> {
299 type Item = (Sysno, &'a T);
300 type IntoIter = SysnoMapIter<'a, T>;
301
302 fn into_iter(self) -> Self::IntoIter {
303 self.iter()
304 }
305}
306
307impl<T> core::ops::Index<Sysno> for SysnoMap<T> {
308 type Output = T;
309
310 fn index(&self, sysno: Sysno) -> &T {
311 self.get(sysno).expect("no entry found for key")
312 }
313}
314
315impl<T> core::ops::IndexMut<Sysno> for SysnoMap<T> {
316 fn index_mut(&mut self, sysno: Sysno) -> &mut T {
317 self.get_mut(sysno).expect("no entry found for key")
318 }
319}
320
321#[cfg(test)]
322mod tests {
323 use super::*;
324
325 #[test]
326 fn test_default() {
327 assert_eq!(SysnoMap::<u8>::new().count(), 0);
328 }
329
330 #[test]
331 fn test_is_empty() {
332 let mut map = SysnoMap::new();
333 assert!(map.is_empty());
334 assert_eq!(map.insert(Sysno::openat, 42), None);
335 assert!(!map.is_empty());
336 assert_eq!(map.get(Sysno::openat), Some(&42));
337 map.remove(Sysno::openat);
338 assert!(map.is_empty());
339 assert_eq!(map.get(Sysno::openat), None);
340 }
341
342 #[test]
343 fn test_count() {
344 let mut map = SysnoMap::new();
345 assert_eq!(map.count(), 0);
346 assert_eq!(map.insert(Sysno::openat, 42), None);
347 assert_eq!(map.count(), 1);
348 assert_eq!(map.insert(Sysno::first(), 4), None);
349 assert_eq!(map.count(), 2);
350 assert_eq!(map.insert(Sysno::last(), 5), None);
351 assert_eq!(map.count(), 3);
352 assert_eq!(map.values().sum::<u8>(), 51);
353 }
354
355 #[test]
356 fn test_fn() {
357 let mut map = SysnoMap::<fn() -> i32>::new();
358 map.insert(Sysno::openat, || 1);
359 map.insert(Sysno::close, || -1);
360 assert_eq!(map.get(Sysno::openat).unwrap()(), 1);
361 assert_eq!(map.get(Sysno::close).unwrap()(), -1);
362 }
363
364 #[test]
365 fn test_fn_macro() {
366 type Handler = fn() -> i32;
367 let map = SysnoMap::from_iter([
368 (Sysno::openat, (|| 1) as Handler),
369 (Sysno::close, (|| -1) as Handler),
370 ]);
371 assert_eq!(map.get(Sysno::openat).unwrap()(), 1);
372 assert_eq!(map.get(Sysno::close).unwrap()(), -1);
373 }
374
375 #[test]
376 fn test_insert_remove() {
377 let mut map = SysnoMap::new();
378 assert_eq!(map.insert(Sysno::openat, 42), None);
379 assert!(map.contains_key(Sysno::openat));
380 assert_eq!(map.count(), 1);
381
382 assert_eq!(map.insert(Sysno::openat, 4), Some(42));
383 assert!(map.contains_key(Sysno::openat));
384 assert_eq!(map.count(), 1);
385
386 assert_eq!(map.remove(Sysno::openat), Some(4));
387 assert!(!map.contains_key(Sysno::openat));
388 assert_eq!(map.count(), 0);
389
390 assert_eq!(map.remove(Sysno::openat), None);
391 }
392
393 #[cfg(feature = "std")]
394 #[test]
395 fn test_debug() {
396 let map = SysnoMap::from_iter([(Sysno::read, 42), (Sysno::openat, 10)]);
397 let result = format!("{:?}", map);
398 assert_eq!(result.len(), "{read: 42, openat: 10}".len());
401 assert!(result.starts_with('{'));
402 assert!(result.ends_with('}'));
403 assert!(result.contains(", "));
404 assert!(result.contains("read: 42"));
405 assert!(result.contains("openat: 10"));
406 }
407
408 #[cfg(feature = "std")]
409 #[test]
410 fn test_iter() {
411 let map = SysnoMap::from_iter([(Sysno::read, 42), (Sysno::openat, 10)]);
412 assert_eq!(map.iter().collect::<Vec<_>>().len(), 2);
413 }
414
415 #[test]
416 fn test_into_iter() {
417 let map = SysnoMap::from_iter([(Sysno::read, 42), (Sysno::openat, 10)]);
418 assert_eq!((&map).into_iter().count(), 2);
419 }
420
421 #[test]
422 fn test_init_all() {
423 let map = SysnoMap::init_all(&42);
424 assert_eq!(map.get(Sysno::openat), Some(&42));
425 assert_eq!(map.get(Sysno::close), Some(&42));
426 }
427}