1use std::alloc;
2use std::ptr;
3use std::mem;
4use std::fmt;
5use core::slice;
6use std::ops::{Index, IndexMut};
7use std::fmt::Display;
8
9type Layout = alloc::Layout;
10
11fn array_layout<T>(count: usize) -> Layout {
12 let layout = alloc::Layout::array::<T>(count).unwrap();
13 assert_ne!(layout.size(), 0);
14 assert_eq!(layout.size(), count * mem::size_of::<T>());
15 layout
16}
17
18fn array_alloc<T>(count: usize) -> *mut T {
20 let layout = array_layout::<T>(count);
21
22 unsafe {
23 alloc::alloc(layout) as *mut T
24 }
25}
26
27fn array_realloc<T>(ptr: *mut T, count: usize, new_count: usize) -> *mut T {
28 if new_count == count {
29 return ptr;
30 }
31
32 let layout = array_layout::<T>(count);
33
34 unsafe {
35 alloc::realloc(
36 ptr as *mut u8,
37 layout,
38 array_layout::<T>(new_count).size()
39 ) as *mut T
40 }
41}
42
43fn array_dealloc<T>(ptr: *mut T, count: usize) {
44 unsafe {
46 alloc::dealloc(
47 ptr as *mut u8,
48 array_layout::<T>(count)
49 )
50 }
51}
52
53
54pub struct Chunks<T: Clone, const BOUNDS_CHECK: bool = true>
55{
56 pub ptr: *mut T,
57 pub count: usize,
58}
59
60impl<
61 T: Copy + Clone,
62 const BC: bool,
63> Chunks<T, BC> {
64
65 pub fn memset_copy(&mut self, value: T) {
66 for i in 0..self.count {
67 self[i] = value;
69 }
70 }
71
72 pub fn filled_copy(value: T, count: usize) -> Self {
74 let mut c: Self = Self::alloc(count);
75 c.memset_copy(value);
76 c
77 }
78
79 pub fn from_slice_copy(from: &[T]) -> Self {
80 let count: usize = from.len();
81 let c = Self::alloc(count);
82
83 if count > 0 {
85 unsafe {
86 ptr::copy(from.as_ptr(), c.ptr, count)
87 }
88 }
89
90 c
91 }
92}
93
94impl<
95 T: Clone + Display,
96 const BC: bool,
97> Chunks<T, BC> {
98 pub fn memset_clone(&mut self, value: T) {
99 for i in 0..self.count {
100 self.write_index(i, value.clone());
104 }
105 }
106
107 pub fn filled_clone(value: T, count: usize) -> Self {
110 let mut c: Self = Self::alloc(count);
111 c.memset_clone(value);
112 c
113 }
114
115}
116
117impl<
118 T: Clone + Display,
119 const BC: bool,
120> Chunks<T, BC> {
121 pub fn from_slice_clone(from: &[T]) -> Self {
122 let count: usize = from.len();
123 let mut c = Self::alloc(count);
124
125 for i in 0..count {
134 c.write_index(i, from[i].clone())
137 }
138
139 c
140 }
141}
142
143
144impl<
145 T: Clone,
146 const BC: bool,
147> Chunks<T, BC> {
148 pub fn alloc(count: usize) -> Self {
150 Self {
151 ptr: array_alloc::<T>(count),
152 count,
153 }
154 }
155
156 pub fn dealloc(&mut self) {
157 if self.allocated() {
158 array_dealloc(self.ptr, self.count);
159 }
160
161 self.ptr = ptr::null::<T>() as *mut T;
162 self.count = 0;
163 }
164
165 pub fn realloc(&mut self, new_count: usize) {
166 if self.allocated() {
167 self.ptr = array_realloc(self.ptr, self.count, new_count);
168 } else {
169 self.ptr = array_alloc(new_count);
170 }
171 self.count = new_count;
172 }
173
174 pub fn grow(&mut self, delta: usize) {
175 if !self.allocated() {
176 return;
179 }
180 self.realloc(self.count + delta);
181 }
182
183 pub fn allocated(&self) -> bool {
184 !self.ptr.is_null() && self.count > 0
185 }
186
187 pub fn as_ptr(&self) -> *const T {
188 self.ptr as *const T
189 }
190
191 pub fn as_mut_ptr(&self) -> *mut T {
192 self.ptr
193 }
194
195 pub fn as_array<const N: usize>(&self) -> Option<&[T; N]> {
196 if N != self.count {
197 None
198 } else {
199 let ptr = self.as_ptr() as *const [T; N];
202 unsafe {
203 Some(&*ptr)
204 }
205 }
206 }
207
208 pub fn as_slice(&self) -> &[T] {
209 unsafe {
210 slice::from_raw_parts(self.ptr, self.count)
211 }
212 }
213
214 pub fn as_mut_slice(&mut self) -> &mut [T] {
215 unsafe {
216 std::slice::from_raw_parts_mut(self.ptr, self.count)
217 }
218 }
219
220 pub fn indices(&self) -> std::ops::Range<usize> {
221 0..self.count
222 }
223
224 fn bounds(&self, index: usize) -> bool {
226 match BC {
227 false => true,
228 true => 0 <= index && index < self.count,
229 }
230 }
231
232 pub fn write_index(&mut self, index: usize, value: T) {
242 let p: *mut T = self.get_mut_ptr(index).unwrap();
244 unsafe {
245 p.write(value);
246 }
247 }
248
249 fn get_ptr(&self, index: usize) -> Result<*const T, &'static str> {
251 if self.bounds(index) {
253 unsafe {
254 Ok(self.ptr.add(index) as *const T)
255 }
256 } else {
257 Err("Index out of bounds")
258 }
259 }
260
261 fn get_mut_ptr(&mut self, index: usize) -> Result<*mut T, &'static str> {
262 if self.bounds(index) {
264 unsafe {
265 Ok(self.ptr.add(index))
266 }
267 } else {
268 Err("Index out of bounds")
269 }
270 }
271
272 fn get_mut(&mut self, index: usize) -> Result<&mut T, &'static str> {
288 if self.bounds(index) {
297 unsafe {
299 Ok(&mut *self.ptr.add(index))
300 }
301 } else {
302 Err("Index out of bounds")
303 }
304 }
305 }
307
308impl<
313 T: Clone,
314 const BC: bool,
315> Index<usize> for Chunks<T, BC> {
316 type Output = T;
317
318 fn index(&self, index: usize) -> &Self::Output {
319 unsafe {
320 &*self.get_ptr(index).unwrap()
321 }
322 }
323}
324
325impl<
326 T: Clone,
327 const BC: bool,
328> IndexMut<usize> for Chunks<T, BC> {
329 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
330 unsafe {
331 &mut *self.get_mut_ptr(index).unwrap()
332 }
333 }
334}
335
336impl<
339 T: Display + Clone,
340 const BC: bool,
341> fmt::Debug for Chunks<T, BC> {
342 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343 write!(f, "Chunks: [").unwrap();
344 for i in 0..self.count {
345 if i > 0 {
346 write!(f, ", ").unwrap();
347 }
348 let val: T = unsafe {
359 self.ptr.add(i).read()
360 };
361 write!(f, "{}", val).unwrap();
362
363 std::mem::forget(val);
365 }
366 write!(f, "]")
367 }
368}
369
370impl<
373 T: Clone,
374 const BC: bool,
375> Drop for Chunks<T, BC> {
376 fn drop(&mut self) {
377 if self.allocated() && false {
378 self.dealloc();
379 }
380 }
381}