malloc_array/
iter.rs

1use super::*;
2
3use std::{
4    mem::{
5	forget,
6    },
7    marker::{
8	Send,Sync,
9    },
10    ops::{
11	Drop,
12    },
13};
14use ptr::{
15    VoidPointer,
16};
17
18/// An iterator that consumes `HeapArray<T>` instance and ensures all memory is appropriately freed when consumed or dropped.
19pub struct IntoIter<T>
20{
21    start: *mut T,
22    current_offset: usize,
23    sz: usize,
24}
25
26unsafe impl<T: Send> Send for IntoIter<T>{}
27unsafe impl<T: Sync> Sync for IntoIter<T>{} //this is probably fine right?
28
29impl<T> IntoIter<T>
30{
31    fn current(&mut self) -> *mut T
32    {
33	unsafe {
34	    self.start.offset(self.current_offset as isize)
35	}
36    }
37    fn free_if_needed(&mut self)
38    {
39	if self.start != ptr::null() && self.current_offset >= self.sz {
40	    unsafe {
41		alloc::free(self.start as VoidPointer);
42	    }
43	    self.start = ptr::null();
44	}
45    }
46    fn drain_if_needed(&mut self)
47    {
48	if self.start != ptr::null() {
49
50	    unsafe {
51		if self.current_offset<self.sz {
52		    for i in self.current_offset..self.sz
53		    {
54			drop(ptr::take(self.start.offset(i as isize)));
55		    }
56		}
57
58		alloc::free(self.start as VoidPointer);
59	    }
60	    self.start = ptr::null();
61	}
62    }
63}
64
65impl<T> Drop for IntoIter<T>
66{
67    fn drop(&mut self)
68    {
69	self.drain_if_needed();
70    }
71}
72
73impl<T> Iterator for IntoIter<T>
74{
75    type Item = T;
76    fn next(&mut self) -> Option<Self::Item>
77    {
78	let output = if self.current_offset >= self.sz || self.sz == 0 {
79	    None
80	} else {
81	    unsafe {
82		let output = crate::ptr::take(self.current());//replace(&mut (*self.current), MaybeUninit::zeroed().assume_init());
83		self.current_offset+=1;
84
85		Some(output)
86	    }
87	};
88	self.free_if_needed();
89	output
90    }
91}
92
93impl<T> ExactSizeIterator for IntoIter<T>
94{
95    fn len(&self) -> usize
96    {
97	self.sz
98    }
99}
100
101impl<T> IntoIterator for HeapArray<T>
102{
103    type Item = T;
104    type IntoIter = IntoIter<T>;
105
106    fn into_iter(self) -> Self::IntoIter
107    {
108	let output = Self::IntoIter {
109	    start: self.ptr,
110	    current_offset: 0,
111	    sz: self.len(),
112	};
113	forget(self);
114	output
115    }
116}