use super::*;
#[derive(Default, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct NonEmptyStack<T>
{
last : T,
stack : Vec<T>
}
impl<T> Deref for NonEmptyStack<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.last }}
impl<T> DerefMut for NonEmptyStack<T> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.last }}
#[allow(clippy::len_without_is_empty)]
impl<T> NonEmptyStack<T>
{
pub const fn new(value : T) -> Self { Self { last: value, stack: Vec::new() }}
pub fn with_capacity(value : T, capacity : usize) -> Self { Self { last: value, stack: Vec::with_capacity(capacity.saturating_sub(1)) }}
pub fn from_vec(mut stack : Vec<T>) -> Option<Self> { stack.pop().and_then(|last| Some(Self{ last, stack })) }
pub fn len(&self) -> usize { self.stack.len() + 1 }
pub const fn last(&self) -> &T { &self.last }
pub const fn last_mut(&mut self) -> &mut T { &mut self.last }
pub fn clear_and_keep_last(&mut self) { self.stack.clear() }
pub fn clear_and_keep_first(&mut self)
{
if self.stack.is_empty() { return; }
std::mem::swap(&mut self.last, &mut self.stack[0]);
self.stack.clear();
}
pub fn replace(&mut self, mut value : T) -> T { std::mem::swap(&mut self.last, &mut value); value }
pub fn push(&mut self, mut value : T) { std::mem::swap(&mut self.last, &mut value); self.stack.push(value); }
pub fn duplicate(&mut self) -> &mut Self where T: Clone { self.stack.push(self.last.clone()); self }
pub fn pop(&mut self) -> Option<T> { self.stack.pop().and_then(|mut v| { std::mem::swap(&mut v, &mut self.last); Some(v) }) }
pub fn iter(&self) -> Iter<'_, T> { Iter { stack: self.stack.iter(), last: Some(&self.last) } }
pub fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { stack: self.stack.iter_mut(), last: Some(&mut self.last) } }
pub fn into_values(mut self) -> Vec<T> { self.stack.push(self.last); self.stack }
}
#[derive(Debug, Clone)]
pub struct IntoIter<T> {
stack: std::vec::IntoIter<T>,
last: Option<T>,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.stack.next().or_else(|| self.last.take())
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.stack.len() + self.last.is_some() as usize;
(len, Some(len))
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.last.is_some() && self.stack.len() == 0 {
self.last.take()
} else {
self.stack.next_back()
}
}
}
impl<T> std::iter::FusedIterator for IntoIter<T> {}
impl<T> std::iter::ExactSizeIterator for IntoIter<T> { fn len(&self) -> usize { self.stack.len() + self.last.is_some() as usize } }
impl<T> IntoIterator for NonEmptyStack<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
stack: self.stack.into_iter(),
last: Some(self.last),
}
}
}
#[derive(Debug, Clone)]
pub struct Iter<'a, T> {
stack: std::slice::Iter<'a, T>,
last: Option<&'a T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.stack.next().or_else(|| self.last.take())
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.stack.len() + self.last.is_some() as usize;
(len, Some(len))
}
}
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.last.is_some() && self.stack.len() == 0 {
self.last.take()
} else {
self.stack.next_back()
}
}
}
impl<'a,T> std::iter::FusedIterator for Iter<'a,T> {}
impl<'a,T> std::iter::ExactSizeIterator for Iter<'a,T> { fn len(&self) -> usize { self.stack.len() + self.last.is_some() as usize } }
impl<'a, T> IntoIterator for &'a NonEmptyStack<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
Iter {
stack: self.stack.iter(),
last: Some(&self.last),
}
}
}
#[derive(Debug)]
pub struct IterMut<'a, T> {
stack: std::slice::IterMut<'a, T>,
last: Option<&'a mut T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.stack.next().or_else(|| self.last.take())
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.stack.len() + self.last.is_some() as usize;
(len, Some(len))
}
}
impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.last.is_some() && self.stack.len() == 0 {
self.last.take()
} else {
self.stack.next_back()
}
}
}
impl<'a,T> std::iter::FusedIterator for IterMut<'a,T> {}
impl<'a,T> std::iter::ExactSizeIterator for IterMut<'a,T> { fn len(&self) -> usize { self.stack.len() + self.last.is_some() as usize } }
impl<'a, T> IntoIterator for &'a mut NonEmptyStack<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
IterMut {
stack: self.stack.iter_mut(),
last: Some(&mut self.last),
}
}
}
impl<T> Index<usize> for NonEmptyStack<T>
{
type Output=T;
fn index(&self, index: usize) -> &Self::Output
{
if index + 1 == self.len()
{
&self.last
}else
{
&self.stack[index]
}
}
}
impl<T> IndexMut<usize> for NonEmptyStack<T>
{
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index + 1 == self.len()
{
&mut self.last
}else
{
&mut self.stack[index]
}
}
}
impl<T> Length for NonEmptyStack<T>
{
fn len(&self) -> usize { self.len() }
fn is_empty(&self) -> bool { false }
fn is_not_empty(&self) -> bool { true }
}
impl<T> Capacity for NonEmptyStack<T>
{
type Param=T;
fn capacity(&self) -> usize { self.stack.capacity() + 1 }
fn with_capacity_and_param(capacity: usize, value : Self::Param) -> Self { Self::with_capacity(value, capacity) }
fn reserve(&mut self, additional: usize) { self.stack.reserve(additional.saturating_sub(1)); }
fn reserve_exact(&mut self, additional: usize) { self.stack.reserve_exact(additional.saturating_sub(1)); }
fn try_reserve(&mut self, additional: usize) -> Result<(), std::collections::TryReserveError> { self.stack.try_reserve(additional.saturating_sub(1)) }
fn try_reserve_exact(&mut self, additional: usize) -> Result<(), std::collections::TryReserveError> { self.stack.try_reserve_exact(additional.saturating_sub(1)) }
}
#[cfg(test)]
mod non_empty_stack_test
{
use super::*;
#[test]
fn push() {
let mut s = NonEmptyStack::new(42);
assert_eq!(s.len(), 1);
assert_eq!(s.last(), &42);
s.push(50);
assert_eq!(s.len(), 2);
assert_eq!(s.last(), &50);
s.duplicate();
assert_eq!(s.len(), 3);
assert_eq!(s.last(), &50);
assert_eq!(s.pop(), Some(50));
assert_eq!(s.len(), 2);
assert_eq!(s.pop(), Some(50));
assert_eq!(s.len(), 1);
assert_eq!(s.pop(), None);
assert_eq!(s.len(), 1);
}
}