use crate::{Error, Slot};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct SlotSpan(Slot);
impl SlotSpan {
pub fn new(head: Slot) -> Self {
Self(head)
}
pub fn iter_sized(self, len: usize) -> SlotSpanIter {
SlotSpanIter::new(self.0, len)
}
pub fn iter(self, len: u16) -> SlotSpanIter {
SlotSpanIter::new_u16(self.0, len)
}
pub fn head(self) -> Slot {
self.0
}
pub fn head_mut(&mut self) -> &mut Slot {
&mut self.0
}
pub fn has_overlapping_copies(results: Self, values: Self, len: u16) -> bool {
SlotSpanIter::has_overlapping_copies(results.iter(len), values.iter(len))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct FixedSlotSpan<const N: u16> {
span: SlotSpan,
}
impl FixedSlotSpan<2> {
pub fn to_array(self) -> [Slot; 2] {
let span = self.span();
let fst = span.head();
let snd = fst.next();
[fst, snd]
}
}
impl<const N: u16> FixedSlotSpan<N> {
pub fn new(span: SlotSpan) -> Result<Self, Error> {
let head = span.head();
if head >= head.next_n(N) {
return Err(Error::StackSlotOutOfBounds);
}
Ok(Self { span })
}
pub unsafe fn new_unchecked(span: SlotSpan) -> Self {
Self { span }
}
pub fn iter(&self) -> SlotSpanIter {
self.span.iter(self.len())
}
pub fn bounded(self) -> BoundedSlotSpan {
BoundedSlotSpan {
span: self.span,
len: N,
}
}
pub fn span(self) -> SlotSpan {
self.span
}
pub fn span_mut(&mut self) -> &mut SlotSpan {
&mut self.span
}
pub fn contains(self, reg: Slot) -> bool {
if self.is_empty() {
return false;
}
let min = self.span.head();
let max = min.next_n(N);
min <= reg && reg < max
}
pub fn len(self) -> u16 {
N
}
pub fn is_empty(self) -> bool {
N == 0
}
}
impl<const N: u16> IntoIterator for &FixedSlotSpan<N> {
type Item = Slot;
type IntoIter = SlotSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<const N: u16> IntoIterator for FixedSlotSpan<N> {
type Item = Slot;
type IntoIter = SlotSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BoundedSlotSpan {
span: SlotSpan,
len: u16,
}
impl BoundedSlotSpan {
pub fn new(span: SlotSpan, len: u16) -> Self {
Self { span, len }
}
pub fn iter(&self) -> SlotSpanIter {
self.span.iter(self.len())
}
pub fn span(&self) -> SlotSpan {
self.span
}
pub fn span_mut(&mut self) -> &mut SlotSpan {
&mut self.span
}
pub fn contains(self, reg: Slot) -> bool {
if self.is_empty() {
return false;
}
let min = self.span.head();
let max = min.next_n(self.len);
min <= reg && reg < max
}
pub fn head(&self) -> Slot {
self.span.head()
}
pub fn len(&self) -> u16 {
self.len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl IntoIterator for &BoundedSlotSpan {
type Item = Slot;
type IntoIter = SlotSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for BoundedSlotSpan {
type Item = Slot;
type IntoIter = SlotSpanIter;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SlotSpanIter {
next: Slot,
last: Slot,
}
impl SlotSpanIter {
pub fn from_raw_parts(start: Slot, end: Slot) -> Self {
debug_assert!(u16::from(start) <= u16::from(end));
Self {
next: start,
last: end,
}
}
fn new(start: Slot, len: usize) -> Self {
let len = u16::try_from(len)
.unwrap_or_else(|_| panic!("out of bounds length for register span: {len}"));
Self::new_u16(start, len)
}
fn new_u16(start: Slot, len: u16) -> Self {
let next = start;
let last = start
.0
.checked_add(len)
.map(Slot)
.expect("overflowing register index for register span");
Self::from_raw_parts(next, last)
}
pub fn span(self) -> SlotSpan {
SlotSpan(self.next)
}
pub fn len_as_u16(&self) -> u16 {
self.last.0.abs_diff(self.next.0)
}
pub fn is_empty(&self) -> bool {
self.len_as_u16() == 0
}
pub fn has_overlapping_copies(results: Self, values: Self) -> bool {
assert_eq!(
results.len(),
values.len(),
"cannot copy between different sized register spans"
);
let len = results.len();
if len <= 1 {
return false;
}
let first_value = values.span().head();
let first_result = results.span().head();
if first_value >= first_result {
return false;
}
let mut values = values;
let last_value = values
.next_back()
.expect("span is non empty and thus must return");
last_value >= first_result
}
}
impl Iterator for SlotSpanIter {
type Item = Slot;
fn next(&mut self) -> Option<Self::Item> {
if self.next == self.last {
return None;
}
let reg = self.next;
self.next = self.next.next();
Some(reg)
}
}
impl DoubleEndedIterator for SlotSpanIter {
fn next_back(&mut self) -> Option<Self::Item> {
if self.next == self.last {
return None;
}
self.last = self.last.prev();
Some(self.last)
}
}
impl ExactSizeIterator for SlotSpanIter {
fn len(&self) -> usize {
usize::from(SlotSpanIter::len_as_u16(self))
}
}