commonlibsse_ng\re\n/
NiTMap.rs

1use core::ffi::c_void;
2use core::fmt::Debug;
3use core::hash::{Hash, Hasher};
4use core::ptr;
5
6use crate::re::NiTDefaultAllocator::NiTDefaultAllocator;
7use crate::re::NiTMapBase::{NiTMapBase, NiTMapBaseVtbl, NiTMapItem};
8
9/// A generic map data structure that supports basic operations like insertion, removal, and lookup.
10///
11/// This type is designed to be compatible with C++'s `NiTMap` and is exposed through FFI bindings.
12///
13/// # Note
14/// As far as the requirements in the vtable are concerned, key is supposed to be a `Copy` type.
15pub struct NiTMap<K, V> {
16    pub __base: NiTMapBase<K, V, NiTDefaultAllocator<NiTMapItem<K, V>>>,
17}
18const _: () = assert!(core::mem::size_of::<NiTMap<*mut c_void, *mut c_void>>() == 0x20);
19
20impl<K, V> NiTMap<K, V> {
21    /// Clears all elements from the map.
22    ///
23    /// This function removes all key-value pairs from the map and resets its state.
24    /// The map will be empty after this operation.
25    #[inline]
26    pub fn clear(&mut self) {
27        self.__base.clear();
28    }
29
30    /// Returns the number of elements in the map.
31    #[inline]
32    pub const fn len(&self) -> usize {
33        self.__base.len()
34    }
35
36    /// Returns `true` if the map is empty, otherwise `false`.
37    #[inline]
38    pub const fn is_empty(&self) -> bool {
39        self.len() == 0
40    }
41}
42
43pub struct NiTMapVtbl<K, V> {
44    pub __base: NiTMapBaseVtbl<K, V, NiTDefaultAllocator<NiTMapItem<K, V>>>,
45}
46
47impl<K, V> NiTMap<K, V>
48where
49    K: Copy,
50{
51    /// Gets a reference to the value associated with the given key.
52    #[inline]
53    pub fn get(&self, key: &K) -> Option<&V> {
54        self.__base.get(key)
55    }
56
57    /// Gets a mutable reference to the value associated with the given key.
58    #[inline]
59    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
60        self.__base.get_mut(key)
61    }
62
63    /// Checks if the map contains the specified key.
64    #[inline]
65    pub fn contains_key(&self, key: &K) -> bool {
66        self.get(key).is_some()
67    }
68
69    /// Inserts a new key-value pair into the map.
70    ///
71    /// If the key already exists in the map, this will replace the existing value.
72    #[inline]
73    pub fn insert(&mut self, key: K, value: V) -> bool {
74        self.__base.insert(key, value)
75    }
76
77    /// Removes the key-value pair associated with the given key.
78    #[inline]
79    pub fn remove(&mut self, key: &K) -> Option<V> {
80        self.__base.remove(key)
81    }
82
83    /// Returns an iterator over the map's key-value pairs.
84    #[inline]
85    pub const fn iter(&self) -> NiTMapIter<K, V> {
86        NiTMapIter { map: &self.__base, bucket_index: 0, current_item: ptr::null_mut() }
87    }
88
89    /// Returns an iterator over the keys in the map.
90    #[inline]
91    pub fn keys(&self) -> impl Iterator<Item = &K> {
92        self.iter().map(|(k, _)| k)
93    }
94
95    /// Returns an iterator over the values in the map.
96    #[inline]
97    pub fn values(&self) -> impl Iterator<Item = &V> {
98        self.iter().map(|(_, v)| v)
99    }
100}
101
102// =====================================================================================================================
103// Debug, PartialEq, Eq, PartialOrd, Ord, Hash
104
105impl<K, V> core::fmt::Debug for NiTMap<K, V>
106where
107    K: Debug + Copy,
108    V: Debug,
109{
110    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111        f.debug_map().entries(self.iter()).finish()
112    }
113}
114
115impl<K: Copy + Clone, V: Clone> Clone for NiTMap<K, V> {
116    #[inline]
117    fn clone(&self) -> Self {
118        // If vptr specified static fn table.
119        let mut new_map = Self { __base: NiTMapBase::new(self.__base.vtable) };
120
121        for (k, v) in self {
122            new_map.insert(*k, v.clone());
123        }
124
125        new_map
126    }
127}
128
129impl<K, V> PartialEq for NiTMap<K, V>
130where
131    K: Eq + Copy,
132    V: PartialEq,
133{
134    #[inline]
135    fn eq(&self, other: &Self) -> bool {
136        self.iter().eq(other.iter())
137    }
138}
139
140impl<K, V> Eq for NiTMap<K, V>
141where
142    K: Eq + Copy,
143    V: Eq,
144{
145}
146
147impl<K, V> PartialOrd for NiTMap<K, V>
148where
149    K: Ord + Copy,
150    V: PartialOrd,
151{
152    #[inline]
153    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
154        self.iter().partial_cmp(other.iter())
155    }
156}
157
158impl<K, V> Ord for NiTMap<K, V>
159where
160    K: Ord + Copy,
161    V: Ord,
162{
163    #[inline]
164    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
165        self.iter().cmp(other.iter())
166    }
167}
168
169impl<K, V> Hash for NiTMap<K, V>
170where
171    K: Hash + Copy,
172    V: Hash,
173{
174    #[inline]
175    fn hash<H: Hasher>(&self, state: &mut H) {
176        for (k, v) in self.iter() {
177            k.hash(state);
178            v.hash(state);
179        }
180    }
181}
182
183// =====================================================================================================================
184
185pub struct NiTMapIter<'a, K, V> {
186    map: &'a NiTMapBase<K, V, NiTDefaultAllocator<NiTMapItem<K, V>>>,
187    bucket_index: usize,
188    current_item: *mut NiTMapItem<K, V>,
189}
190
191impl<'a, K, V> Iterator for NiTMapIter<'a, K, V> {
192    type Item = (&'a K, &'a V);
193
194    fn next(&mut self) -> Option<Self::Item> {
195        while self.bucket_index < self.map.capacity as usize {
196            if !self.current_item.is_null() {
197                let item = unsafe { &*self.current_item };
198                self.current_item = item.next;
199                return Some((&item.key, &item.value));
200            }
201
202            self.current_item = unsafe { *self.map.data.add(self.bucket_index) };
203            self.bucket_index += 1;
204        }
205        None
206    }
207}
208
209impl<'a, K, V> IntoIterator for &'a NiTMap<K, V> {
210    type Item = (&'a K, &'a V);
211    type IntoIter = NiTMapIter<'a, K, V>;
212
213    #[inline]
214    fn into_iter(self) -> Self::IntoIter {
215        NiTMapIter { map: &self.__base, bucket_index: 0, current_item: ptr::null_mut() }
216    }
217}
218
219pub struct NiTMapIntoIter<K, V> {
220    inner: NiTMap<K, V>,
221    bucket_index: usize,
222    current_item: *mut NiTMapItem<K, V>,
223}
224
225impl<K, V> Iterator for NiTMapIntoIter<K, V>
226where
227    K: Copy,
228{
229    type Item = (K, V);
230
231    fn next(&mut self) -> Option<Self::Item> {
232        while self.bucket_index < self.inner.__base.capacity as usize {
233            if !self.current_item.is_null() {
234                let item = unsafe { &*self.current_item };
235                let result = Some((item.key, unsafe { ptr::read(&item.value) }));
236                self.current_item = item.next;
237                return result;
238            }
239
240            self.current_item = unsafe { *self.inner.__base.data.add(self.bucket_index) };
241            self.bucket_index += 1;
242        }
243        None
244    }
245}
246
247impl<K, V> IntoIterator for NiTMap<K, V>
248where
249    K: Copy,
250{
251    type Item = (K, V);
252    type IntoIter = NiTMapIntoIter<K, V>;
253
254    #[inline]
255    fn into_iter(self) -> Self::IntoIter {
256        NiTMapIntoIter { inner: self, bucket_index: 0, current_item: ptr::null_mut() }
257    }
258}
259
260impl<K: Copy, V> Extend<(K, V)> for NiTMap<K, V> {
261    #[inline]
262    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
263        for (k, v) in iter {
264            self.insert(k, v);
265        }
266    }
267}
268
269// =====================================================================================================================