You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
3.1 KiB

use super::*;
use std::{
marker::PhantomData,
};
/// Iterator for initialising potentially uninitialised `HeapArray<T>`.
pub struct InitIter<'a, T>
{
from: &'a mut HeapArray<T>,
current_idex: usize,
}
/// A safe wrapper to initialise potentially uninitialised data.
pub struct Init<'a, T>
{
ptr: *mut T,
init_ok: bool,
_marker: PhantomData<&'a T>,
}
impl<'a, T> InitIter<'a, T>
{
pub(crate) fn new(from: &'a mut HeapArray<T>, current_idex: usize) -> InitIter<'a, T>
{
InitIter {
from,
current_idex,
}
}
/// Consumes the instance, zeroing all remaining bytes in the iterator.
pub fn uninit(self)
{
let len = self.from.len_bytes() - (self.current_idex * HeapArray::<T>::element_size());
if len > 0 {
unsafe {
ptr::memset(self.from.as_mut_ptr().offset(self.current_idex as isize) as *mut u8, 0, len);
}
}
}
}
impl<'a, T> Iterator for InitIter<'a, T>
{
type Item = Init<'a, T>;
fn next(&mut self) -> Option<Self::Item>
{
if self.current_idex >= self.from.len() {
None
} else {
self.current_idex+=1;
unsafe {
Some(Init{
ptr: self.from.as_mut_ptr().offset((self.current_idex as isize)-1),
init_ok: false,
_marker: PhantomData,
})
}
}
}
}
pub trait InitIterExt<T>
{
/// Fill the rest of the iterator with a `clone()`d value.
fn fill(self, value: T) where T: Clone;
/// Fill the rest of the iterator with output from a function.
fn fill_with<F>(self, func: F) where F: FnMut() -> T;
/// Fill the rest of the iterator with `default()`
fn fill_default(self) where T: Default;
}
impl<'a, T,I> InitIterExt<T> for I
where I: Iterator<Item=Init<'a, T>>,
T: 'a
{
fn fill(self, value: T)
where T:Clone
{
for mut x in self
{
if !x.is_init() {
x.put(value.clone());
}
}
}
fn fill_with<F>(self, mut func: F)
where F: FnMut() -> T
{
for mut x in self
{
if !x.is_init() {
x.put(func());
}
}
}
fn fill_default(self)
where T:Default
{
for mut x in self
{
if !x.is_init() {
x.put(Default::default());
}
}
}
}
impl<'a, T> Init<'a, T>
{
/// Has the value been set with `put()` or `assume_init()` yet?
pub fn is_init(&self) -> bool
{
self.init_ok
}
/// Assume the value has been initialised.
pub unsafe fn assume_init(&mut self)
{
self.init_ok = true;
}
/// Initialise or reset the value and then return a mutable reference to it.
pub fn put(&mut self, value: T) -> &mut T
{
if self.init_ok {
unsafe {
*self.ptr = value;
return &mut (*self.ptr);
}
}
self.init_ok = true;
unsafe {
ptr::put(self.ptr, value);
&mut (*self.ptr)
}
}
/// Get a reference to the value if it has been initialised.
pub fn get(&self) -> Option<&T>
{
unsafe {
if self.init_ok {
Some(& (*self.ptr))
} else {
None
}
}
}
/// Get a mutable reference to the value if it has been initialised.
pub fn get_mut(&mut self) -> Option<&mut T>
{
unsafe {
if self.init_ok {
Some(&mut (*self.ptr))
} else {
None
}
}
}
}