use super::*;
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VolBlock<T, R, W, const C: usize> {
base: VolAddress<T, R, W>,
}
impl<T, R, W, const C: usize> VolBlock<T, R, W, C> {
#[inline]
#[must_use]
pub const unsafe fn new(base: usize) -> Self {
Self { base: VolAddress::new(base) }
}
#[inline]
#[must_use]
pub const unsafe fn len(self) -> usize {
C
}
#[inline]
#[must_use]
#[track_caller]
pub const fn index(self, i: usize) -> VolAddress<T, R, W> {
if i < C {
unsafe { self.base.add(i) }
} else {
#[allow(unconditional_panic)]
unsafe {
VolAddress::new([usize::MAX][1])
}
}
}
#[inline]
#[must_use]
pub const fn get(self, i: usize) -> Option<VolAddress<T, R, W>> {
if i < C {
Some(unsafe { self.base.add(i) })
} else {
None
}
}
#[inline]
#[must_use]
pub const fn iter(self) -> VolBlockIter<T, R, W> {
VolBlockIter { base: self.base, count: C }
}
}
impl<T, R, W, const C: usize> Clone for VolBlock<T, R, W, C> {
#[inline]
#[must_use]
fn clone(&self) -> Self {
*self
}
}
impl<T, R, W, const C: usize> Copy for VolBlock<T, R, W, C> {}
impl<T, R, W, const C: usize> core::fmt::Debug for VolBlock<T, R, W, C> {
#[cold]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "VolBlock<{elem_ty}, r{readability}, w{writeability}, c{count}>({address:#X})",
elem_ty = core::any::type_name::<T>(),
readability=core::any::type_name::<R>(),
writeability=core::any::type_name::<W>(),
count=C,
address=self.base.address.get())
}
}
#[repr(C)]
pub struct VolBlockIter<T, R, W> {
pub(crate) base: VolAddress<T, R, W>,
pub(crate) count: usize,
}
impl<T, R, W> Clone for VolBlockIter<T, R, W> {
#[inline]
#[must_use]
fn clone(&self) -> Self {
Self { base: self.base, count: self.count }
}
}
impl<T, R, W> core::iter::Iterator for VolBlockIter<T, R, W> {
type Item = VolAddress<T, R, W>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
let out = Some(self.base);
self.count -= 1;
self.base = unsafe { self.base.add(1) };
out
} else {
None
}
}
#[inline]
#[must_use]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.count, Some(self.count))
}
#[inline]
#[must_use]
fn count(self) -> usize {
self.count
}
#[inline]
#[must_use]
fn last(self) -> Option<Self::Item> {
if self.count > 0 {
Some(unsafe { self.base.add(self.count - 1) })
} else {
None
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if n < self.count {
self.count -= n;
self.base = unsafe { self.base.add(1 + n) };
Some(self.base)
} else {
self.count = 0;
None
}
}
}
impl<T, R, W> core::iter::DoubleEndedIterator for VolBlockIter<T, R, W> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.count > 0 {
let out = Some(unsafe { self.base.add(self.count - 1) });
self.count -= 1;
out
} else {
None
}
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
if n < self.count {
self.count -= n;
Some(unsafe { self.base.add(1 + n) })
} else {
self.count = 0;
None
}
}
}
#[test]
#[allow(bad_style)]
fn test_impl_Iterator_for_VolBlockIter() {
let i: VolBlockIter<u16, (), ()> = VolBlockIter {
base: unsafe { VolAddress::new(core::mem::align_of::<u16>()) },
count: 4,
};
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.next(), Some(2));
assert_eq!(i_c.next(), Some(4));
assert_eq!(i_c.next(), Some(6));
assert_eq!(i_c.next(), Some(8));
assert_eq!(i_c.next(), None);
assert_eq!(i_c.next(), None);
let i_c = i.clone();
assert_eq!(i_c.size_hint(), (4, Some(4)));
let i_c = i.clone();
assert_eq!(i_c.count(), 4);
let i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.last(), Some(8));
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth(0), Some(2));
assert_eq!(i_c.nth(0), Some(4));
assert_eq!(i_c.nth(0), Some(6));
assert_eq!(i_c.nth(0), Some(8));
assert_eq!(i_c.nth(0), None);
assert_eq!(i_c.nth(0), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth(1), Some(4));
assert_eq!(i_c.nth(1), Some(8));
assert_eq!(i_c.nth(1), None);
assert_eq!(i_c.nth(1), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth(2), Some(6));
assert_eq!(i_c.nth(2), None);
assert_eq!(i_c.nth(2), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth(3), Some(8));
assert_eq!(i_c.nth(3), None);
assert_eq!(i_c.nth(3), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth(4), None);
assert_eq!(i_c.nth(4), None);
}
#[test]
#[allow(bad_style)]
fn test_impl_DoubleEndedIterator_for_VolBlockIter() {
let i: VolBlockIter<u16, (), ()> = VolBlockIter {
base: unsafe { VolAddress::new(core::mem::align_of::<u16>()) },
count: 4,
};
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.next_back(), Some(8));
assert_eq!(i_c.next_back(), Some(6));
assert_eq!(i_c.next_back(), Some(4));
assert_eq!(i_c.next_back(), Some(2));
assert_eq!(i_c.next_back(), None);
assert_eq!(i_c.next_back(), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth_back(0), Some(8));
assert_eq!(i_c.nth_back(0), Some(6));
assert_eq!(i_c.nth_back(0), Some(4));
assert_eq!(i_c.nth_back(0), Some(2));
assert_eq!(i_c.nth_back(0), None);
assert_eq!(i_c.nth_back(0), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth_back(1), Some(6));
assert_eq!(i_c.nth_back(1), Some(2));
assert_eq!(i_c.nth_back(1), None);
assert_eq!(i_c.nth_back(1), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth_back(2), Some(4));
assert_eq!(i_c.nth_back(2), None);
assert_eq!(i_c.nth_back(2), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth_back(3), Some(2));
assert_eq!(i_c.nth_back(3), None);
assert_eq!(i_c.nth_back(3), None);
let mut i_c = i.clone().map(|a| a.as_usize());
assert_eq!(i_c.nth_back(4), None);
assert_eq!(i_c.nth_back(4), None);
}