#![allow(dead_code)]
use core::fmt::{Debug, Error, Formatter};
use tarrasque::{ExtractError, ExtractResult, Stream};
use crate::error::{OVERFLOW, UNDERFLOW};
const SIZE: usize = 10;
#[derive(Copy, Clone)]
pub struct SubroutineStack<'s> {
buffer: [Stream<'s>; SIZE],
size: usize,
}
impl<'s> SubroutineStack<'s> {
#[inline]
pub fn new() -> Self {
Self { buffer: [Stream(&[]); SIZE], size: 0 }
}
#[inline]
pub fn len(&self) -> usize {
self.size
}
#[inline]
pub fn is_empty(&self) -> bool {
self.size == 0
}
#[inline]
pub fn push(&mut self, value: Stream<'s>) -> ExtractResult<'s, ()> {
if self.size < self.buffer.len() {
self.buffer[self.size] = value;
self.size += 1;
Ok(())
} else {
Err(ExtractError::Code(OVERFLOW))
}
}
#[inline]
pub fn pop(&mut self) -> ExtractResult<'s, Stream<'s>> {
if !self.is_empty() {
self.size -= 1;
Ok(self.buffer[self.size])
} else {
Err(ExtractError::Code(UNDERFLOW))
}
}
}
impl<'s> Debug for SubroutineStack<'s> {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.debug_list().entries((0..self.size).map(|i| self.buffer[i])).finish()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_subroutine_stack() {
let streams = &[
Stream(&[1]), Stream(&[2]), Stream(&[3]), Stream(&[4]), Stream(&[5]),
Stream(&[6]), Stream(&[7]), Stream(&[8]), Stream(&[9]), Stream(&[10]),
];
let mut stack = SubroutineStack::new();
for stream in streams {
stack.push(*stream).unwrap();
}
assert_eq!(stack.push(Stream(&[11])), Err(ExtractError::Code(OVERFLOW)));
for stream in streams.iter().rev() {
assert_eq!(stack.pop().unwrap(), *stream);
}
assert_eq!(stack.pop(), Err(ExtractError::Code(UNDERFLOW)));
}
}