use core::{
fmt::{Debug, Display},
iter::FusedIterator,
ops::{Index, IndexMut},
};
#[derive(Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Debug)]
pub struct UxnStack {
pub data: [u8; 0x100],
pub pointer: u8,
}
impl Default for UxnStack {
fn default() -> Self {
Self::new()
}
}
impl UxnStack {
pub const fn new() -> Self {
Self {
pointer: 0,
data: [0u8; 0x100],
}
}
pub fn iter(&self) -> UxnStackIter<'_> {
UxnStackIter::new(self)
}
pub fn iter_mut(&mut self) -> UxnStackIterMut<'_> {
UxnStackIterMut::new(self)
}
pub fn top(&self) -> u8 {
self.data[self.pointer.wrapping_sub(1) as usize]
}
pub fn top_mut(&mut self) -> &mut u8 {
&mut self.data[self.pointer.wrapping_sub(1) as usize]
}
pub fn top_short(&self) -> u16 {
u16::from_be_bytes([self[-1], self[0]])
}
pub fn set_top_short(&mut self, value: u16) {
let [msb, lsb] = value.to_be_bytes();
self[-1] = msb;
self[0] = lsb;
}
pub fn get(&self, index: i8) -> u8 {
self.data[self.pointer.wrapping_add_signed(index).wrapping_sub(1) as usize]
}
pub fn get_mut(&mut self, index: i8) -> &mut u8 {
&mut self.data[self.pointer.wrapping_add_signed(index).wrapping_sub(1) as usize]
}
pub fn get_short(&self, index: i8) -> u16 {
u16::from_be_bytes([self[index.wrapping_sub(1)], self[index]])
}
pub fn set_short(&mut self, index: i8, value: u16) {
let [msb, lsb] = value.to_be_bytes();
self[index.wrapping_sub(1)] = msb;
self[index] = lsb;
}
pub fn push(&mut self, value: u8) {
self[1] = value;
self.pointer = self.pointer.wrapping_add(1);
}
pub fn pop(&mut self) -> u8 {
self.pointer = self.pointer.wrapping_sub(1);
self[1]
}
pub fn push_short(&mut self, value: u16) {
let [msb, lsb] = value.to_be_bytes();
self[1] = msb;
self[2] = lsb;
self.pointer = self.pointer.wrapping_add(2);
}
pub fn pop_short(&mut self) -> u16 {
self.pointer = self.pointer.wrapping_sub(2);
u16::from_be_bytes([self[1], self[2]])
}
pub fn remove(&mut self, index: i8) -> u8 {
let value = self.get(index);
let mut ptr = self.pointer.wrapping_add_signed(index).wrapping_sub(1);
loop {
self.data[ptr as usize] = self.data[ptr.wrapping_add(1) as usize];
ptr = ptr.wrapping_add(1);
if ptr == self.pointer {
break;
}
}
self.pointer = self.pointer.wrapping_sub(1);
value
}
pub fn insert(&mut self, index: i8, value: u8) {
let mut ptr = self.pointer.wrapping_add_signed(index);
loop {
self.data[ptr.wrapping_add(1) as usize] = self.data[ptr as usize];
ptr = ptr.wrapping_add(1);
if ptr == self.pointer {
break;
}
}
self[index.wrapping_add(1)] = value;
self.pointer = self.pointer.wrapping_add(1);
}
pub fn remove_short(&mut self, index: i8) -> u16 {
let value = self.get_short(index);
let mut ptr = self.pointer.wrapping_add_signed(index).wrapping_sub(2);
loop {
self.data[ptr as usize] = self.data[ptr.wrapping_add(2) as usize];
ptr = ptr.wrapping_add(1);
if ptr == self.pointer {
break;
}
}
self.pointer = self.pointer.wrapping_sub(2);
value
}
pub fn insert_short(&mut self, index: i8, value: u16) {
let mut ptr = self.pointer.wrapping_add_signed(index);
loop {
self.data[ptr.wrapping_add(2) as usize] = self.data[ptr as usize];
ptr = ptr.wrapping_add(1);
if ptr == self.pointer {
break;
}
}
self.set_short(index.wrapping_add(2), value);
self.pointer = self.pointer.wrapping_add(2);
}
}
impl Index<i8> for UxnStack {
type Output = u8;
fn index(&self, index: i8) -> &Self::Output {
&self.data[self.pointer.wrapping_add_signed(index).wrapping_sub(1) as usize]
}
}
impl IndexMut<i8> for UxnStack {
fn index_mut(&mut self, index: i8) -> &mut Self::Output {
self.get_mut(index)
}
}
impl PartialEq<[u8; 0x100]> for UxnStack {
fn eq(&self, other: &[u8; 0x100]) -> bool {
&self.data == other
}
}
impl Display for UxnStack {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for i in -7..=1 {
write!(f, "{:#04x}{} ", self.get(i), if i == 0 { "|" } else { "" })?
}
Ok(())
}
}
pub struct UxnStackIter<'a> {
left: &'a [u8],
right: &'a [u8],
}
impl<'a> UxnStackIter<'a> {
pub fn new(stack: &'a UxnStack) -> Self {
let (left, right) = stack.data.split_at(stack.pointer as usize);
Self { left, right }
}
}
impl<'a> Iterator for UxnStackIter<'a> {
type Item = &'a u8;
fn next(&mut self) -> Option<Self::Item> {
if let Some((last, rest)) = self.left.split_last() {
self.left = rest;
Some(last)
} else if let Some((last, rest)) = self.right.split_last() {
self.right = rest;
Some(last)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(256, Some(256))
}
}
impl DoubleEndedIterator for UxnStackIter<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
if let Some((first, rest)) = self.right.split_first() {
self.right = rest;
Some(first)
} else if let Some((first, rest)) = self.left.split_first() {
self.left = rest;
Some(first)
} else {
None
}
}
}
impl ExactSizeIterator for UxnStackIter<'_> {
fn len(&self) -> usize {
256
}
}
impl FusedIterator for UxnStackIter<'_> {}
pub struct UxnStackIterMut<'a> {
left: &'a mut [u8],
right: &'a mut [u8],
}
impl<'a> UxnStackIterMut<'a> {
pub fn new(stack: &'a mut UxnStack) -> Self {
let (left, right) = stack.data.split_at_mut(stack.pointer as usize);
Self { left, right }
}
}
impl<'a> Iterator for UxnStackIterMut<'a> {
type Item = &'a mut u8;
fn next(&mut self) -> Option<Self::Item> {
if let Some((last, rest)) = core::mem::take(&mut self.left).split_last_mut() {
self.left = rest;
Some(last)
} else if let Some((last, rest)) = core::mem::take(&mut self.right).split_last_mut() {
self.right = rest;
Some(last)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(256, Some(256))
}
}
impl DoubleEndedIterator for UxnStackIterMut<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
if let Some((first, rest)) = core::mem::take(&mut self.right).split_first_mut() {
self.right = rest;
Some(first)
} else if let Some((first, rest)) = core::mem::take(&mut self.left).split_first_mut() {
self.left = rest;
Some(first)
} else {
None
}
}
}
impl ExactSizeIterator for UxnStackIterMut<'_> {
fn len(&self) -> usize {
256
}
}
impl FusedIterator for UxnStackIterMut<'_> {}