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