commonlibsse_ng\re\m\MemoryManager/
SimpleArray.rs1use core::alloc::Layout;
2use core::cmp::Ordering;
3use core::hash::{Hash, Hasher};
4use core::mem::MaybeUninit;
5use core::ptr::{self, NonNull};
6use core::slice;
7use std::alloc::handle_alloc_error;
8
9use crate::re::MemoryManager::TESGlobalAlloc;
10use stdx::alloc::Allocator;
11use stdx::ptr::{ConstNonNull, Unique};
12
13pub struct SimpleArray<T, A: Allocator = TESGlobalAlloc> {
30 data: Option<Unique<T>>,
31 alloc: A,
32}
33const _: () = assert!(core::mem::size_of::<SimpleArray<i32>>() == core::mem::size_of::<usize>());
34
35impl<T> SimpleArray<T> {
36 #[inline]
45 pub const fn new() -> Self {
46 Self { data: None, alloc: TESGlobalAlloc }
47 }
48
49 #[inline]
63 pub fn with_capacity(count: usize) -> Self {
64 let mut array = Self::new();
65 array.resize(count);
66 array
67 }
68}
69
70impl<T, A> SimpleArray<T, A>
71where
72 A: Allocator,
73{
74 #[inline]
85 pub const fn new_in(data: Option<Unique<T>>, alloc: A) -> Self {
86 Self { data, alloc }
87 }
88
89 #[inline]
100 pub const fn len(&self) -> usize {
101 match self.len_ptr() {
102 Some(ptr) => unsafe { ptr.read() },
103 None => 0,
104 }
105 }
106
107 #[inline]
116 pub const fn is_empty(&self) -> bool {
117 self.len() == 0
118 }
119
120 #[inline]
133 pub fn clear(&mut self) {
134 if self.data.is_none() && self.is_empty() {
135 return;
136 }
137
138 if let Some(len_ptr) = self.len_ptr_mut() {
139 unsafe { ptr::drop_in_place(self.as_mut_slice()) };
140 unsafe { self.alloc.deallocate(len_ptr.cast(), Self::layout(self.len())) };
141 self.data = None; }
143 }
144
145 pub fn resize(&mut self, count: usize) {
158 if count == 0 {
159 self.clear();
160 return;
161 }
162
163 let old_size = self.len();
164 if old_size == count {
165 return;
166 }
167
168 unsafe {
169 let layout = Self::layout(count);
170 let Ok(new_head) = self.alloc.allocate(layout) else { handle_alloc_error(layout) };
171 let new_head = new_head.cast::<usize>();
172 new_head.write(count); let new_data = new_head.add(1).cast::<T>();
175
176 if let Some(prev_data) = self.data {
178 let prev_data = prev_data.as_ptr();
179 let new_data = new_data.as_ptr();
180 if count < old_size {
181 ptr::copy_nonoverlapping(prev_data, new_data, count);
182 } else {
183 ptr::copy_nonoverlapping(prev_data, new_data, old_size);
184 for i in old_size..count {
185 ptr::write(new_data.add(i), MaybeUninit::zeroed().assume_init());
186 }
187 }
188 } else {
189 ptr::write_bytes(new_data.as_ptr(), MaybeUninit::zeroed().assume_init(), count);
190 }
191
192 self.clear(); self.data = Some(Unique::from(new_data));
195 }
196 }
197
198 #[inline]
211 pub fn get(&self, index: usize) -> Option<&T> {
212 if index < self.len() { unsafe { Some(self.data()?.add(index).as_ref()) } } else { None }
213 }
214
215 #[inline]
230 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
231 if index < self.len() { unsafe { Some(self.data()?.add(index).as_mut()) } } else { None }
232 }
233
234 #[inline]
245 pub const fn as_ptr(&self) -> *mut T {
246 match self.data {
247 Some(non_null) => non_null.as_ptr(),
248 None => ptr::null_mut(),
249 }
250 }
251
252 #[inline]
265 pub const fn as_mut_slice(&mut self) -> &mut [T] {
266 let len = self.len();
267 if len == 0 {
268 return &mut [];
269 }
270
271 match self.data {
272 Some(ptr) => unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) },
273 None => &mut [],
274 }
275 }
276
277 #[inline]
290 pub const fn as_slice(&self) -> &[T] {
291 let len = self.len();
292 if len == 0 {
293 return &[];
294 }
295
296 match self.data {
297 Some(ptr) => unsafe { slice::from_raw_parts(ptr.as_ptr(), len) },
298 None => &[],
299 }
300 }
301
302 #[inline]
304 const fn len_ptr(&self) -> Option<ConstNonNull<usize>> {
305 match self.data {
306 Some(data) => unsafe {
307 let ptr = data.as_non_null_ptr().cast::<usize>().sub(1);
308 ConstNonNull::new(ptr.as_ptr())
309 },
310 None => None,
311 }
312 }
313
314 #[inline]
316 const fn len_ptr_mut(&mut self) -> Option<NonNull<usize>> {
317 match self.data.as_mut() {
318 Some(data) => unsafe { Some(data.as_non_null_ptr().cast::<usize>().sub(1)) },
319 None => None,
320 }
321 }
322
323 #[inline]
325 const fn data(&self) -> Option<NonNull<T>> {
326 match self.data {
327 Some(data) => Some(data.as_non_null_ptr()),
328 None => None,
329 }
330 }
331
332 fn layout(count: usize) -> Layout {
337 let layout = {
338 const LEN_SIZE: usize = core::mem::size_of::<usize>(); const LEN_ALIGN: usize = core::mem::align_of::<usize>(); let alloc_size = LEN_SIZE + (core::mem::size_of::<T>() * count);
343
344 let alignment = LEN_ALIGN.max(core::mem::align_of::<T>());
348
349 Layout::from_size_align(alloc_size, alignment)
350 };
351
352 match layout {
353 Ok(layout) => layout,
354 Err(err) => panic!("SimpleArray alloc overflow: need size > isize::MAX: {err}"),
355 }
356 }
357
358 #[inline]
378 pub const fn iter(&self) -> SimpleArrayIterator<'_, T, A> {
379 SimpleArrayIterator { array: self, index: 0, len: self.len() }
380 }
381}
382
383impl<T, A: Allocator> Drop for SimpleArray<T, A> {
384 fn drop(&mut self) {
385 if self.data.is_none() && self.is_empty() {
386 return;
387 }
388
389 if let Some(len_ptr) = self.len_ptr_mut() {
392 unsafe { ptr::drop_in_place(self.as_mut_slice()) };
393 unsafe { self.alloc.deallocate(len_ptr.cast(), Self::layout(self.len())) };
394 }
395 }
396}
397
398impl<T> Default for SimpleArray<T> {
399 #[inline]
400 fn default() -> Self {
401 Self::new()
402 }
403}
404
405impl<T: PartialEq, A: Allocator> PartialEq for SimpleArray<T, A> {
406 fn eq(&self, other: &Self) -> bool {
407 if self.len() != other.len() {
408 return false;
409 }
410 for i in 0..self.len() {
411 if self.get(i) != other.get(i) {
412 return false;
413 }
414 }
415 true
416 }
417}
418
419impl<T: Eq, A: Allocator> Eq for SimpleArray<T, A> {}
420
421impl<T: PartialOrd, A: Allocator> PartialOrd for SimpleArray<T, A> {
422 #[inline]
423 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
424 if self.len() != other.len() {
425 return None;
426 }
427 for i in 0..self.len() {
428 match self[i].partial_cmp(&other[i]) {
429 Some(Ordering::Equal) => {}
430 Some(ordering) => return Some(ordering),
431 None => return None,
432 }
433 }
434 Some(Ordering::Equal)
435 }
436}
437
438impl<T: Ord, A: Allocator> Ord for SimpleArray<T, A> {
439 #[inline]
440 fn cmp(&self, other: &Self) -> Ordering {
441 if self.len() != other.len() {
442 return self.len().cmp(&other.len());
443 }
444 for i in 0..self.len() {
445 match self[i].cmp(&other[i]) {
446 Ordering::Equal => {}
447 ordering => return ordering,
448 }
449 }
450 Ordering::Equal
451 }
452}
453
454impl<T: Hash, A: Allocator> Hash for SimpleArray<T, A> {
455 #[inline]
456 fn hash<H: Hasher>(&self, state: &mut H) {
457 for i in 0..self.len() {
458 self.get(i).hash(state);
459 }
460 }
461}
462
463impl<T, A: Allocator> core::ops::Index<usize> for SimpleArray<T, A> {
464 type Output = T;
465
466 #[inline]
467 fn index(&self, index: usize) -> &Self::Output {
468 assert!(index < self.len(), "Index out of bounds");
469 unsafe { self.data().expect("Accessing empty array").add(index).as_ref() }
470 }
471}
472
473impl<T, A: Allocator> core::ops::IndexMut<usize> for SimpleArray<T, A> {
474 #[inline]
475 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
476 assert!(index < self.len(), "Index out of bounds");
477 unsafe { self.data().expect("Accessing empty array").add(index).as_mut() }
478 }
479}
480
481pub struct SimpleArrayIterator<'a, T, A>
483where
484 A: Allocator,
485{
486 array: &'a SimpleArray<T, A>,
487 index: usize,
488 len: usize, }
490
491impl<'a, T, A: Allocator> Iterator for SimpleArrayIterator<'a, T, A> {
492 type Item = &'a T;
493
494 #[inline]
495 fn next(&mut self) -> Option<Self::Item> {
496 if self.index < self.len {
497 let item = unsafe { self.array.data()?.add(self.index).as_ref() };
498 self.index += 1;
499 Some(item)
500 } else {
501 None
502 }
503 }
504}
505
506pub struct SimpleArrayIntoIterator<T, A: Allocator> {
508 array: SimpleArray<T, A>,
509 index: usize,
510 len: usize, }
512
513impl<T, A: Allocator> Iterator for SimpleArrayIntoIterator<T, A> {
514 type Item = T;
515
516 #[inline]
517 fn next(&mut self) -> Option<Self::Item> {
518 if self.index < self.len {
519 let item = unsafe { ptr::read(self.array.data()?.add(self.index).as_ptr()) };
520 self.index += 1;
521 Some(item)
522 } else {
523 None
524 }
525 }
526}
527
528impl<T, A: Allocator> IntoIterator for SimpleArray<T, A> {
529 type Item = T;
530 type IntoIter = SimpleArrayIntoIterator<T, A>;
531
532 #[inline]
533 fn into_iter(self) -> Self::IntoIter {
534 let len = self.len();
535 SimpleArrayIntoIterator { array: self, index: 0, len }
536 }
537}
538
539impl<'a, T, A: Allocator> IntoIterator for &'a SimpleArray<T, A> {
540 type Item = &'a T;
541 type IntoIter = SimpleArrayIterator<'a, T, A>;
542
543 #[inline]
544 fn into_iter(self) -> Self::IntoIter {
545 self.iter()
546 }
547}
548
549#[cfg(test)]
550mod tests {
551 use super::*;
552
553 #[test]
554 fn test_new() {
555 let array: SimpleArray<i32> = SimpleArray::new();
556 assert_eq!(array.len(), 0);
557 assert!(array.is_empty());
558 }
559
560 #[test]
561 fn test_with_capacity() {
562 let array: SimpleArray<i32> = SimpleArray::with_capacity(5);
563 assert_eq!(array.len(), 5);
564 assert!(!array.is_empty());
565 }
566
567 #[test]
568 fn test_resize_grow() {
569 let mut array = SimpleArray::<u32>::with_capacity(3);
570 array.resize(5);
571 assert_eq!(array.len(), 5);
572 }
573
574 #[test]
575 fn test_resize_shrink() {
576 let mut array = SimpleArray::<u32>::with_capacity(5);
577 array.resize(2);
578 assert_eq!(array.len(), 2);
579 }
580
581 #[test]
582 fn test_data_access() {
583 let mut array = SimpleArray::with_capacity(3);
584 let slice = array.as_mut_slice();
585 slice[0] = 10;
586 slice[1] = 20;
587 slice[2] = 30;
588
589 let new_slice = array.as_slice();
590 assert_eq!(new_slice, &[10, 20, 30]);
591 }
592
593 #[test]
594 fn test_clear() {
595 let mut array = SimpleArray::<u32>::with_capacity(3);
597 array.clear();
598 assert_eq!(array.len(), 0);
599 assert!(array.is_empty());
600 }
601
602 #[test]
603 fn test_as_slice() {
604 let mut array = SimpleArray::with_capacity(4);
605 let slice = array.as_mut_slice();
606 slice.copy_from_slice(&[1, 2, 3, 4]);
607
608 let new_slice = array.as_slice();
609 assert_eq!(new_slice, &[1, 2, 3, 4]);
610 }
611
612 #[test]
613 fn test_into_iterator() {
614 let mut array = SimpleArray::with_capacity(5);
615 let slice = array.as_mut_slice();
616 slice[0] = 10;
617 slice[1] = 20;
618 slice[2] = 30;
619 slice[3] = 40;
620 slice[4] = 50;
621
622 let collected: Vec<_> = array.into_iter().collect();
623 assert_eq!(collected, vec![10, 20, 30, 40, 50]);
624 }
625
626 #[test]
627 fn test_iterator() {
628 let mut array = SimpleArray::with_capacity(5);
629 array[0] = 10;
630 array[1] = 20;
631 array[2] = 30;
632 array[3] = 40;
633 array[4] = 50;
634
635 let mut iter = array.iter();
636 assert_eq!(iter.next(), Some(&10));
637 assert_eq!(iter.next(), Some(&20));
638 assert_eq!(iter.next(), Some(&30));
639 assert_eq!(iter.next(), Some(&40));
640 assert_eq!(iter.next(), Some(&50));
641 assert_eq!(iter.next(), None); }
643}