malloc_array/
init.rs

1use super::*;
2use std::{
3    marker::PhantomData,
4};
5
6/// Iterator for initialising potentially uninitialised `HeapArray<T>`.
7pub struct InitIter<'a, T>
8{
9    from: &'a mut HeapArray<T>,
10    current_idex: usize,
11}
12
13/// A safe wrapper to initialise potentially uninitialised data.
14pub struct Init<'a, T>
15{
16    ptr: *mut T,
17    init_ok: bool,
18    _marker: PhantomData<&'a T>,
19}
20
21impl<'a, T> InitIter<'a, T>
22{
23    pub(crate) fn new(from: &'a mut HeapArray<T>, current_idex: usize) -> InitIter<'a, T>
24    {
25	InitIter {
26	    from,
27	    current_idex,
28	}
29    }
30
31    /// Consumes the instance, zeroing all remaining bytes in the iterator.
32    pub fn uninit(self)
33    {
34	let len = self.from.len_bytes() - (self.current_idex * HeapArray::<T>::element_size());
35	if len > 0 {
36	    unsafe {
37		ptr::memset(self.from.as_mut_ptr().offset(self.current_idex as isize) as *mut u8, 0, len);
38	    }
39	}
40    }
41}
42
43impl<'a, T> Iterator for InitIter<'a, T>
44{
45    type Item = Init<'a, T>;
46
47    fn next(&mut self) -> Option<Self::Item>
48    {
49	if self.current_idex >= self.from.len() {
50	    None
51	} else {
52	    self.current_idex+=1;
53	    unsafe {
54		Some(Init{
55		    ptr: self.from.as_mut_ptr().offset((self.current_idex as isize)-1),
56		    init_ok: false,
57		    _marker: PhantomData,
58		})
59	    }
60	}
61    }
62}
63
64pub trait InitIterExt<T>
65{
66
67    /// Fill the rest of the iterator with a `clone()`d value.
68    fn fill(self, value: T) where T: Clone;
69
70    /// Fill the rest of the iterator with output from a function.
71    fn fill_with<F>(self, func: F) where F: FnMut() -> T;
72
73    /// Fill the rest of the iterator with `default()`
74    fn fill_default(self) where T: Default;
75}
76
77impl<'a, T,I> InitIterExt<T> for I
78where I: Iterator<Item=Init<'a, T>>,
79      T: 'a
80{
81    fn fill(self, value: T)
82    where T:Clone
83    {
84	for mut x in self
85	{
86	    if !x.is_init() {
87		x.put(value.clone());
88	    }
89	}
90    }
91    fn fill_with<F>(self, mut func: F)
92    where F: FnMut() -> T
93    {
94	for mut x in self
95	{
96	    if !x.is_init() {
97		x.put(func());
98	    }
99	}
100    }
101    fn fill_default(self)
102    where T:Default
103    {
104	for mut x in self
105	{
106	    if !x.is_init() {
107		x.put(Default::default());
108	    }
109	}
110    }
111}
112
113impl<'a, T> Init<'a, T>
114{
115
116    /// Has the value been set with `put()` or `assume_init()` yet?
117    pub fn is_init(&self) -> bool
118    {
119	self.init_ok
120    }
121
122    /// Assume the value has been initialised.
123    pub unsafe fn assume_init(&mut self)
124    {
125	self.init_ok = true;
126    }
127
128    /// Initialise or reset the value and then return a mutable reference to it.
129    pub fn put(&mut self, value: T) -> &mut T
130    {
131	if self.init_ok {
132	    unsafe {
133		*self.ptr = value;	
134		return &mut (*self.ptr);
135	    }
136	}
137	self.init_ok = true;
138	unsafe {
139	    ptr::put(self.ptr, value);
140	    &mut (*self.ptr)
141	}
142    }
143
144    /// Get a reference to the value if it has been initialised.
145    pub fn get(&self) -> Option<&T>
146    {
147	unsafe {
148	    if self.init_ok {
149		Some(& (*self.ptr))
150	    } else {
151		None
152	    }
153	}
154    }
155
156    /// Get a mutable reference to the value if it has been initialised.
157    pub fn get_mut(&mut self) -> Option<&mut T>
158    {
159	unsafe {
160	    if self.init_ok {
161		Some(&mut (*self.ptr))
162	    } else {
163		None
164	    }
165	}
166    }
167}