use core::{iter::FusedIterator, marker::PhantomData};
use super::Register;
pub struct RegisterIterator<T>
where
T: Register,
{
index: u32,
end: u32,
phantom: PhantomData<T>,
}
impl<T> RegisterIterator<T>
where
T: Register,
{
#[must_use]
pub fn new() -> Self {
Self {
index: 0,
end: T::count() as u32,
phantom: PhantomData,
}
}
}
impl<T> Default for RegisterIterator<T>
where
T: Register,
{
fn default() -> Self {
Self::new()
}
}
impl<T> Iterator for RegisterIterator<T>
where
T: Register + TryFrom<u32>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.end {
None
} else {
let reg = T::try_from(self.index).ok();
self.index = self.index.saturating_add(1);
reg
}
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.index = self.index.saturating_add(n as u32);
self.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.end.saturating_sub(self.index) as usize;
(remaining, Some(remaining))
}
fn count(mut self) -> usize {
let count = self.size_hint().0;
self.index = self.end;
count
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
fn is_sorted(self) -> bool {
true
}
fn max(self) -> Option<Self::Item> {
self.last()
}
fn min(mut self) -> Option<Self::Item> {
self.next()
}
}
impl<T> DoubleEndedIterator for RegisterIterator<T>
where
T: Register + TryFrom<u32>,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.index >= self.end {
None
} else {
self.end = self.end.saturating_sub(1);
T::try_from(self.end).ok()
}
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.end = self.end.saturating_sub(n as u32);
self.next_back()
}
}
impl<T> ExactSizeIterator for RegisterIterator<T> where T: Register + TryFrom<u32> {}
impl<T> FusedIterator for RegisterIterator<T> where T: Register + TryFrom<u32> {}
#[cfg(test)]
mod tests {
use super::*;
use crate::registers::Gpr;
#[test]
#[allow(clippy::cognitive_complexity)]
fn test_iterator_gpr() {
let mut gpr_iter = Gpr::iter();
assert_eq!(gpr_iter.next(), Some(Gpr::zero));
assert_eq!(gpr_iter.next(), Some(Gpr::at));
assert_eq!(gpr_iter.next(), Some(Gpr::v0));
assert_eq!(gpr_iter.next(), Some(Gpr::v1));
assert_eq!(gpr_iter.next(), Some(Gpr::a0));
assert_eq!(gpr_iter.next(), Some(Gpr::a1));
assert_eq!(gpr_iter.next(), Some(Gpr::a2));
assert_eq!(gpr_iter.next(), Some(Gpr::a3));
assert_eq!(gpr_iter.next(), Some(Gpr::t0));
assert_eq!(gpr_iter.next(), Some(Gpr::t1));
assert_eq!(gpr_iter.next(), Some(Gpr::t2));
assert_eq!(gpr_iter.next(), Some(Gpr::t3));
assert_eq!(gpr_iter.next(), Some(Gpr::t4));
assert_eq!(gpr_iter.next(), Some(Gpr::t5));
assert_eq!(gpr_iter.next(), Some(Gpr::t6));
assert_eq!(gpr_iter.next(), Some(Gpr::t7));
assert_eq!(gpr_iter.next(), Some(Gpr::s0));
assert_eq!(gpr_iter.next(), Some(Gpr::s1));
assert_eq!(gpr_iter.next(), Some(Gpr::s2));
assert_eq!(gpr_iter.next(), Some(Gpr::s3));
assert_eq!(gpr_iter.next(), Some(Gpr::s4));
assert_eq!(gpr_iter.next(), Some(Gpr::s5));
assert_eq!(gpr_iter.next(), Some(Gpr::s6));
assert_eq!(gpr_iter.next(), Some(Gpr::s7));
assert_eq!(gpr_iter.next(), Some(Gpr::t8));
assert_eq!(gpr_iter.next(), Some(Gpr::t9));
assert_eq!(gpr_iter.next(), Some(Gpr::k0));
assert_eq!(gpr_iter.next(), Some(Gpr::k1));
assert_eq!(gpr_iter.next(), Some(Gpr::gp));
assert_eq!(gpr_iter.next(), Some(Gpr::sp));
assert_eq!(gpr_iter.next(), Some(Gpr::s8));
assert_eq!(gpr_iter.next(), Some(Gpr::ra));
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn test_iterator_gpr_back() {
let mut gpr_iter = Gpr::iter();
assert_eq!(gpr_iter.next_back(), Some(Gpr::ra));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s8));
assert_eq!(gpr_iter.next_back(), Some(Gpr::sp));
assert_eq!(gpr_iter.next_back(), Some(Gpr::gp));
assert_eq!(gpr_iter.next_back(), Some(Gpr::k1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::k0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t9));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t8));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s7));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s6));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s5));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s4));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s2));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t7));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t6));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t5));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t4));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t2));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::a3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::a2));
assert_eq!(gpr_iter.next_back(), Some(Gpr::a1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::a0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::v1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::v0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::at));
assert_eq!(gpr_iter.next_back(), Some(Gpr::zero));
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
}
#[test]
#[allow(clippy::cognitive_complexity)]
fn test_iterator_gpr_forward_back() {
let mut gpr_iter = Gpr::iter();
assert_eq!(gpr_iter.next(), Some(Gpr::zero));
assert_eq!(gpr_iter.next(), Some(Gpr::at));
assert_eq!(gpr_iter.next(), Some(Gpr::v0));
assert_eq!(gpr_iter.next(), Some(Gpr::v1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::ra));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s8));
assert_eq!(gpr_iter.next_back(), Some(Gpr::sp));
assert_eq!(gpr_iter.next_back(), Some(Gpr::gp));
assert_eq!(gpr_iter.next(), Some(Gpr::a0));
assert_eq!(gpr_iter.next(), Some(Gpr::a1));
assert_eq!(gpr_iter.next(), Some(Gpr::a2));
assert_eq!(gpr_iter.next(), Some(Gpr::a3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::k1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::k0));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t9));
assert_eq!(gpr_iter.next_back(), Some(Gpr::t8));
assert_eq!(gpr_iter.next(), Some(Gpr::t0));
assert_eq!(gpr_iter.next(), Some(Gpr::t1));
assert_eq!(gpr_iter.next(), Some(Gpr::t2));
assert_eq!(gpr_iter.next(), Some(Gpr::t3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s7));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s6));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s5));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s4));
assert_eq!(gpr_iter.next(), Some(Gpr::t4));
assert_eq!(gpr_iter.next(), Some(Gpr::t5));
assert_eq!(gpr_iter.next(), Some(Gpr::t6));
assert_eq!(gpr_iter.next(), Some(Gpr::t7));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s3));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s2));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s1));
assert_eq!(gpr_iter.next_back(), Some(Gpr::s0));
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next_back(), None);
}
#[test]
fn test_iterator_gpr_nth() {
let mut gpr_iter = Gpr::iter().skip(31);
assert_eq!(gpr_iter.next(), Some(Gpr::ra));
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
let mut gpr_iter = Gpr::iter();
assert_eq!(gpr_iter.nth(31), Some(Gpr::ra));
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next(), None);
let mut gpr_iter = Gpr::iter();
assert_eq!(gpr_iter.nth_back(31), Some(Gpr::zero));
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(gpr_iter.next(), None);
assert_eq!(gpr_iter.next_back(), None);
assert_eq!(Gpr::iter().count(), Gpr::count());
let gpr_iter = Gpr::iter().skip(8);
assert_eq!(gpr_iter.count(), Gpr::count() - 8);
}
#[test]
fn test_iterator_gpr_last() {
assert_eq!(Gpr::iter().last(), Some(Gpr::ra));
let gpr_iter = Gpr::iter().skip(32);
assert_eq!(gpr_iter.last(), None);
let mut gpr_iter = Gpr::iter();
gpr_iter.next_back();
gpr_iter.next_back();
assert_eq!(gpr_iter.last(), Some(Gpr::sp));
}
}