1use std::{ffi::c_void, ptr::NonNull};
2
3use crate::gc;
4
5pub fn from_fn<T>(len: usize, mut f: impl FnMut(usize) -> T) -> &'static mut [T] {
6 let vec = VecInner::<T>::new(len);
7 for i in 0..len {
8 unsafe { vec.as_ptr().add(i).write(f(i)) };
9 }
10 vec.set_len(len);
11
12 register_finalizer(vec.as_ptr());
13
14 unsafe { std::slice::from_raw_parts_mut(vec.as_ptr(), len) }
15}
16
17pub fn repeat<T: Clone>(val: T, len: usize) -> &'static mut [T] {
18 from_fn(len, |_| val.clone())
19}
20
21pub fn from_iter<T, I: IntoIterator<Item = T>>(iter: I) -> &'static mut [T] {
22 let iter = iter.into_iter();
23 let (lower, _) = iter.size_hint();
24
25 let mut cap = lower.max(1);
26 let mut vec = VecInner::<T>::new(cap);
27 let mut len = 0;
28 for item in iter {
29 if len == cap {
30 cap = cap.checked_mul(2).expect("Capacity overflow");
31 let new_vec = VecInner::<T>::new(cap);
32 unsafe { std::ptr::copy_nonoverlapping(vec.as_ptr(), new_vec.as_ptr(), len) };
33 vec = new_vec;
34 }
35 unsafe { vec.as_ptr().add(len).write(item) };
36 len += 1;
37 }
38 vec.set_len(len);
39
40 register_finalizer(vec.as_ptr());
41
42 unsafe { std::slice::from_raw_parts_mut(vec.as_ptr(), len) }
43}
44
45fn register_finalizer<T>(ptr: *mut T) {
46 if std::mem::needs_drop::<T>() {
47 extern "C" fn finalizer<T>(obj: *mut c_void, _: *mut c_void) {
48 let vec = VecInner(unsafe { NonNull::new_unchecked(obj as *mut T) });
49 let len = vec.num_to_drop();
50 for i in 0..len {
51 unsafe { std::ptr::drop_in_place(vec.as_ptr().add(i)) };
52 }
53 }
54
55 unsafe {
56 gc::GC_register_finalizer(
57 ptr as *mut std::ffi::c_void,
58 Some(finalizer::<T>),
59 std::ptr::null_mut(),
60 std::ptr::null_mut(),
61 std::ptr::null_mut(),
62 );
63 }
64 }
65}
66
67struct VecInner<T>(NonNull<T>);
68
69impl<T> VecInner<T> {
70 fn new(cap: usize) -> Self {
71 if std::mem::needs_drop::<T>() {
72 let padding = usize::max(std::mem::size_of::<usize>(), std::mem::size_of::<T>());
73 let alignment = usize::max(std::mem::align_of::<usize>(), std::mem::align_of::<T>());
74
75 let ptr = unsafe {
76 gc::GC_memalign(
77 std::mem::size_of::<T>().strict_mul(cap).strict_add(padding),
78 alignment,
79 ) as *mut T
80 };
81 let ptr = unsafe {
82 NonNull::new(ptr)
83 .expect("Allocation failed")
84 .byte_add(padding)
85 };
86 VecInner(ptr)
87 } else {
88 let ptr = unsafe {
89 gc::GC_memalign(
90 std::mem::size_of::<T>().strict_mul(cap),
91 std::mem::align_of::<T>(),
92 ) as *mut T
93 };
94 let ptr = NonNull::new(ptr).expect("Allocation failed");
95 VecInner(ptr)
96 }
97 }
98
99 fn as_ptr(&self) -> *mut T {
100 self.0.as_ptr()
101 }
102
103 fn num_to_drop(&self) -> usize {
104 if std::mem::needs_drop::<T>() {
105 let p_len =
106 unsafe { self.0.as_ptr().byte_sub(std::mem::size_of::<usize>()) as *const usize };
107 unsafe { p_len.read() }
108 } else {
109 0
110 }
111 }
112
113 fn set_len(&self, len: usize) {
114 if std::mem::needs_drop::<T>() {
115 let p_len =
116 unsafe { self.0.as_ptr().byte_sub(std::mem::size_of::<usize>()) as *mut usize };
117 unsafe { p_len.write(len) };
118 }
119 }
120}