use std::{marker::PhantomData, slice};
use crate::{iter::Coordinates, pixel, region::Region};
pub struct Iter<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
inner: Coordinates,
owner: Region,
data: &'a mut [C],
stride: usize,
pixel: PhantomData<P>,
channel: PhantomData<C>,
}
impl<'a, P, C> Iter<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
#[doc(hidden)]
#[inline]
pub fn new(data: &mut [C], stride: usize, owner: Region, region: Region) -> Iter<P, C> {
Iter {
inner: Coordinates::new(region),
owner,
data,
stride,
pixel: PhantomData,
channel: PhantomData,
}
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct Item<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
pixel: PhantomData<P>,
channel: PhantomData<C>,
data: &'a mut [C],
}
impl<'a, P, C> Item<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
#[doc(hidden)]
#[inline]
pub fn new(data: &mut [C]) -> Item<P, C> {
Item {
pixel: PhantomData,
channel: PhantomData,
data,
}
}
#[inline]
pub fn get(&self) -> P {
P::read(self.data)
}
#[inline]
pub fn set(&mut self, pixel: &P) {
pixel.write(self.data)
}
}
impl<'a, P, C> Iterator for Iter<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
type Item = (u32, u32, Item<'a, P, C>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let (x, y) = if let Some((x, y)) = self.inner.next() {
(x, y)
}
else {
return None;
};
let channels = P::channels();
let index = (y as usize * self.stride) + (x as usize * channels);
Some((
x - self.inner.region().x,
y - self.inner.region().y,
Item::new(unsafe {
let slice = &self.data[index..index + channels];
slice::from_raw_parts_mut(slice.as_ptr() as *mut _, slice.len())
}),
))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, P, C> ExactSizeIterator for Iter<'a, P, C>
where
P: pixel::Read<C> + pixel::Write<C>,
C: pixel::Channel,
{
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}