use core::{cmp::Ordering, iter::FusedIterator, marker::PhantomData, num::NonZeroUsize};
#[repr(transparent)]
pub struct WOVolAddress<T> {
address: NonZeroUsize,
marker: PhantomData<*mut T>,
}
impl<T> Clone for WOVolAddress<T> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for WOVolAddress<T> {}
impl<T> PartialEq for WOVolAddress<T> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.address == other.address
}
}
impl<T> Eq for WOVolAddress<T> {}
impl<T> PartialOrd for WOVolAddress<T> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.address.cmp(&other.address))
}
}
impl<T> Ord for WOVolAddress<T> {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
self.address.cmp(&other.address)
}
}
impl<T> core::fmt::Debug for WOVolAddress<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "WOVolAddress({:p})", *self)
}
}
impl<T> core::fmt::Pointer for WOVolAddress<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:p}", self.address.get() as *mut T)
}
}
impl<T> WOVolAddress<T> {
#[inline(always)]
pub const unsafe fn new(address: usize) -> Self {
Self {
address: NonZeroUsize::new_unchecked(address),
marker: PhantomData,
}
}
#[inline(always)]
pub const unsafe fn cast<Z>(self) -> WOVolAddress<Z> {
WOVolAddress {
address: self.address,
marker: PhantomData,
}
}
#[inline(always)]
pub const unsafe fn offset(self, offset: isize) -> Self {
Self {
address: NonZeroUsize::new_unchecked(self.address.get().wrapping_add(offset as usize * core::mem::size_of::<T>())),
marker: PhantomData,
}
}
#[inline(always)]
pub const fn is_aligned(self) -> bool {
self.address.get() % core::mem::align_of::<T>() == 0
}
#[inline(always)]
pub const fn to_usize(self) -> usize {
self.address.get()
}
#[inline(always)]
pub const unsafe fn iter_slots(self, slots: usize) -> WOVolIter<T> {
WOVolIter {
vol_address: self,
slots_remaining: slots,
}
}
#[inline(always)]
pub fn write(self, val: T) {
unsafe { (self.address.get() as *mut T).write_volatile(val) }
}
}
pub struct WOVolBlock<T, const COUNT: usize> {
vol_address: WOVolAddress<T>,
}
impl<T, const COUNT: usize> Clone for WOVolBlock<T, COUNT> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T, const COUNT: usize> Copy for WOVolBlock<T, COUNT> {}
impl<T, const COUNT: usize> PartialEq for WOVolBlock<T, COUNT> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.vol_address == other.vol_address
}
}
impl<T, const COUNT: usize> Eq for WOVolBlock<T, COUNT> {}
impl<T, const COUNT: usize> core::fmt::Debug for WOVolBlock<T, COUNT> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "WOVolBlock({:p}, count={})", self.vol_address.address.get() as *mut T, COUNT)
}
}
impl<T, const COUNT: usize> WOVolBlock<T, COUNT> {
#[inline(always)]
pub const unsafe fn new(address: usize) -> Self {
Self {
vol_address: WOVolAddress::new(address),
}
}
#[inline(always)]
pub const fn len(self) -> usize {
COUNT
}
#[inline(always)]
pub const fn iter(self) -> WOVolIter<T> {
WOVolIter {
vol_address: self.vol_address,
slots_remaining: COUNT,
}
}
#[inline(always)]
pub const unsafe fn index_unchecked(self, slot: usize) -> WOVolAddress<T> {
self.vol_address.offset(slot as isize)
}
#[inline(always)]
pub fn index(self, slot: usize) -> WOVolAddress<T> {
if slot < COUNT {
unsafe { self.index_unchecked(slot) }
} else {
panic!("Index Requested: {} >= Slot Count: {}", slot, COUNT)
}
}
#[inline(always)]
pub fn get(self, slot: usize) -> Option<WOVolAddress<T>> {
if slot < COUNT {
unsafe { Some(self.index_unchecked(slot)) }
} else {
None
}
}
}
pub struct WOVolSeries<T, const COUNT: usize, const STRIDE: usize> {
vol_address: WOVolAddress<T>,
}
impl<T, const COUNT: usize, const STRIDE: usize> Clone for WOVolSeries<T, COUNT, STRIDE> {
#[inline(always)]
fn clone(&self) -> Self {
*self
}
}
impl<T, const COUNT: usize, const STRIDE: usize> Copy for WOVolSeries<T, COUNT, STRIDE> {}
impl<T, const COUNT: usize, const STRIDE: usize> PartialEq for WOVolSeries<T, COUNT, STRIDE> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.vol_address == other.vol_address
}
}
impl<T, const COUNT: usize, const STRIDE: usize> Eq for WOVolSeries<T, COUNT, STRIDE> {}
impl<T, const COUNT: usize, const STRIDE: usize> core::fmt::Debug for WOVolSeries<T, COUNT, STRIDE> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"WOVolSeries({:p}, count={}, series={})",
self.vol_address.address.get() as *mut T,
COUNT,
STRIDE
)
}
}
impl<T, const COUNT: usize, const STRIDE: usize> WOVolSeries<T, COUNT, STRIDE> {
#[inline(always)]
pub const unsafe fn new(address: usize) -> Self {
Self {
vol_address: WOVolAddress::new(address),
}
}
#[inline(always)]
pub const fn len(self) -> usize {
COUNT
}
#[inline(always)]
pub const fn iter(self) -> WOVolStridingIter<T, STRIDE> {
WOVolStridingIter {
vol_address: self.vol_address,
slots_remaining: COUNT,
}
}
#[inline(always)]
pub const unsafe fn index_unchecked(self, slot: usize) -> WOVolAddress<T> {
self.vol_address.cast::<u8>().offset((STRIDE * slot) as isize).cast::<T>()
}
#[inline(always)]
pub fn index(self, slot: usize) -> WOVolAddress<T> {
if slot < COUNT {
unsafe { self.index_unchecked(slot) }
} else {
panic!("Index Requested: {} >= Slot Count: {}", slot, COUNT)
}
}
#[inline(always)]
pub fn get(self, slot: usize) -> Option<WOVolAddress<T>> {
if slot < COUNT {
unsafe { Some(self.index_unchecked(slot)) }
} else {
None
}
}
}
pub struct WOVolIter<T> {
vol_address: WOVolAddress<T>,
slots_remaining: usize,
}
impl<T> Clone for WOVolIter<T> {
#[inline(always)]
fn clone(&self) -> Self {
Self {
vol_address: self.vol_address,
slots_remaining: self.slots_remaining,
}
}
}
impl<T> PartialEq for WOVolIter<T> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.vol_address == other.vol_address && self.slots_remaining == other.slots_remaining
}
}
impl<T> Eq for WOVolIter<T> {}
impl<T> Iterator for WOVolIter<T> {
type Item = WOVolAddress<T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.slots_remaining > 0 {
let out = self.vol_address;
unsafe {
self.slots_remaining -= 1;
self.vol_address = self.vol_address.offset(1);
}
Some(out)
} else {
None
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.slots_remaining, Some(self.slots_remaining))
}
#[inline(always)]
fn count(self) -> usize {
self.slots_remaining
}
#[inline(always)]
fn last(self) -> Option<Self::Item> {
if self.slots_remaining > 0 {
Some(unsafe { self.vol_address.offset(self.slots_remaining as isize) })
} else {
None
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.slots_remaining > n {
unsafe {
let out = self.vol_address.offset(n as isize);
let jump = n + 1;
self.slots_remaining -= jump;
self.vol_address = self.vol_address.offset(jump as isize);
Some(out)
}
} else {
self.slots_remaining = 0;
None
}
}
#[inline(always)]
fn max(self) -> Option<Self::Item> {
self.last()
}
#[inline(always)]
fn min(mut self) -> Option<Self::Item> {
self.nth(0)
}
}
impl<T> FusedIterator for WOVolIter<T> {}
impl<T> core::fmt::Debug for WOVolIter<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"WOVolIter({:p}, remaining={})",
self.vol_address.address.get() as *mut T,
self.slots_remaining
)
}
}
pub struct WOVolStridingIter<T, const STRIDE: usize> {
vol_address: WOVolAddress<T>,
slots_remaining: usize,
}
impl<T, const STRIDE: usize> Clone for WOVolStridingIter<T, STRIDE> {
#[inline(always)]
fn clone(&self) -> Self {
Self {
vol_address: self.vol_address,
slots_remaining: self.slots_remaining,
}
}
}
impl<T, const STRIDE: usize> PartialEq for WOVolStridingIter<T, STRIDE> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.vol_address == other.vol_address && self.slots_remaining == other.slots_remaining
}
}
impl<T, const STRIDE: usize> Eq for WOVolStridingIter<T, STRIDE> {}
impl<T, const STRIDE: usize> Iterator for WOVolStridingIter<T, STRIDE> {
type Item = WOVolAddress<T>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.slots_remaining > 0 {
let out = self.vol_address;
unsafe {
self.slots_remaining -= 1;
self.vol_address = self.vol_address.cast::<u8>().offset(STRIDE as isize).cast::<T>();
}
Some(out)
} else {
None
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.slots_remaining, Some(self.slots_remaining))
}
#[inline(always)]
fn count(self) -> usize {
self.slots_remaining
}
#[inline(always)]
fn last(self) -> Option<Self::Item> {
if self.slots_remaining > 0 {
Some(unsafe {
self
.vol_address
.cast::<u8>()
.offset((STRIDE * self.slots_remaining) as isize)
.cast::<T>()
})
} else {
None
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.slots_remaining > n {
unsafe {
let out = self.vol_address.cast::<u8>().offset((STRIDE * n) as isize).cast::<T>();
let jump = n + 1;
self.slots_remaining -= jump;
self.vol_address = self.vol_address.cast::<u8>().offset((STRIDE * jump) as isize).cast::<T>();
Some(out)
}
} else {
self.slots_remaining = 0;
None
}
}
#[inline(always)]
fn max(self) -> Option<Self::Item> {
self.last()
}
#[inline(always)]
fn min(mut self) -> Option<Self::Item> {
self.nth(0)
}
}
impl<T, const STRIDE: usize> FusedIterator for WOVolStridingIter<T, STRIDE> {}
impl<T, const STRIDE: usize> core::fmt::Debug for WOVolStridingIter<T, STRIDE> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"WOVolStridingIter({:p}, remaining={}, stride={})",
self.vol_address.address.get() as *mut T,
self.slots_remaining,
STRIDE
)
}
}