use super::raw_jagged::RawJagged;
use crate::implementations::{
jagged_arrays::{as_raw_slice::AsRawSlice, indexer::JaggedIndexer},
ptr_utils::take,
};
pub struct RawJaggedIterOwned<T, X>
where
X: JaggedIndexer,
{
jagged: RawJagged<T, X>,
f: usize,
current_ptr: *const T,
current_last: *const T,
}
impl<T, X> RawJaggedIterOwned<T, X>
where
X: JaggedIndexer,
{
pub(crate) fn new(mut jagged: RawJagged<T, X>) -> Self {
let num_taken = match jagged.num_taken() {
Some(num_taken) => {
unsafe { jagged.set_num_taken(Some(jagged.len())) };
num_taken
}
None => jagged.len(),
};
let taken_jagged_idx = match num_taken < jagged.len() {
true => jagged.jagged_index(num_taken),
false => None,
};
let (f, current_ptr, current_last) = match taken_jagged_idx {
None => (jagged.num_arrays(), core::ptr::null(), core::ptr::null()),
Some(idx) => {
let [f, i] = [idx.f, idx.i];
let vec = unsafe { jagged.get_unchecked(f) };
let [first, last] = vec.first_and_last_ptrs();
let current = unsafe { first.add(i) };
(f + 1 , current, last)
}
};
Self {
jagged,
f,
current_ptr,
current_last,
}
}
fn next_vec(&mut self) -> Option<T> {
match self.jagged.get(self.f) {
Some(slice) if slice.is_empty() => self.next_vec(),
Some(slice) => {
[self.current_ptr, self.current_last] = slice.first_and_last_ptrs();
self.f += 1;
self.next()
}
None => None,
}
}
fn drop_next_vec(&mut self) -> bool {
match self.jagged.get(self.f) {
Some(slice) if slice.is_empty() => self.drop_next_vec(),
Some(slice) => {
[self.current_ptr, self.current_last] = slice.first_and_last_ptrs();
self.f += 1;
self.drop_next()
}
None => false,
}
}
fn drop_next(&mut self) -> bool {
match self.current_ptr.is_null() {
false => {
let is_last_of_slice = self.current_ptr == self.current_last;
unsafe { (self.current_ptr as *mut T).drop_in_place() };
self.current_ptr = match is_last_of_slice {
false => unsafe { self.current_ptr.add(1) },
true => core::ptr::null_mut(),
};
true
}
true => self.drop_next_vec(),
}
}
}
impl<T, X> Iterator for RawJaggedIterOwned<T, X>
where
X: JaggedIndexer,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.current_ptr.is_null() {
false => {
let is_last_of_slice = self.current_ptr == self.current_last;
let ptr = self.current_ptr as *mut T;
self.current_ptr = match is_last_of_slice {
false => unsafe { self.current_ptr.add(1) },
true => core::ptr::null_mut(),
};
Some(unsafe { take(ptr) })
}
true => self.next_vec(),
}
}
}
impl<T, X> Drop for RawJaggedIterOwned<T, X>
where
X: JaggedIndexer,
{
fn drop(&mut self) {
while self.drop_next() {}
}
}