use std::mem;
use std::fmt::Debug;
use std::hash::Hash;
use stack::Stack;
use adapton::engine::Name;
#[derive(Debug,PartialEq,Eq,Clone,Hash)]
pub struct AStack<E:'static+Debug+Clone+Eq+Hash,M:'static+Debug+Clone+Eq+Hash> {
current: Vec<E>,
archived: Stack<(M,Vec<E>)>,
}
#[derive(Clone)]
pub struct AtHead<T: 'static+Debug+Clone+Eq+Hash,M:'static+Debug+Clone+Eq+Hash>(
pub AStack<T,M>
);
#[derive(Clone)]
pub struct AtTail<T: 'static+Debug+Clone+Eq+Hash,M:'static+Debug+Clone+Eq+Hash>(
pub AStack<T,M>
);
impl<E:'static+Debug+Clone+Eq+Hash, M:'static+Debug+Clone+Eq+Hash>
AStack<E,M> {
pub fn new() -> Self {
AStack {
current: Vec::new(),
archived: Stack::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
AStack {
current: Vec::with_capacity(capacity),
archived: Stack::new(),
}
}
pub fn is_empty(&self) -> bool { self.current.len() == 0 && self.archived.is_empty()}
pub fn active_len(&self) -> usize { self.current.len() }
pub fn name(&self) -> Option<Name> { self.archived.name() }
pub fn push(&mut self, elm: E) { self.current.push(elm) }
pub fn pop(&mut self) -> Option<E> {
if self.is_empty() { return None }
self.retrieve();
self.current.pop()
}
pub fn pop_meta(&mut self) -> Option<(E,Option<M>)> {
if self.is_empty() { return None }
let meta = self.retrieve();
self.current.pop().map(|e|{(e,meta)})
}
#[doc(hidden)]
pub fn extend(&mut self, extra: &[E]) {
self.current.extend_from_slice(extra);
}
#[doc(hidden)]
pub fn extend_rev(&mut self, extra: &[E]) {
self.current.extend_from_slice(extra);
self.current.reverse();
}
pub fn next_archive(&mut self) -> Option<(Vec<E>,Option<M>)> {
if self.is_empty() { return None }
if self.archived.is_empty() {
let old_vec = mem::replace(&mut self.current, Vec::new());
self.archived = Stack::new();
return Some((old_vec,None));
} else {
let (old_meta,vec) = self.archived.peek().expect("missing data");
let old_vec = mem::replace(&mut self.current, vec);
self.archived = self.archived.pull().unwrap();
return Some((old_vec, Some(old_meta)));
}
}
pub fn active_data(&self) -> &Vec<E> {
&self.current
}
pub fn peek(&self) -> Option<E> {
if self.is_empty() { return None }
if self.current.len() == 0 {
let (_,v) = self.archived.peek().unwrap();
Some(v.last().unwrap().clone())
} else { Some(self.current.last().unwrap().clone()) }
}
pub fn archive(&mut self, name: Option<Name>, meta: M) -> bool {
self.archive_with_capacity(name,meta, 0)
}
pub fn archive_with_capacity(&mut self, name: Option<Name>, meta: M, capacity: usize) -> bool {
if self.current.len() == 0 { return false; }
let old_vec = mem::replace(&mut self.current, Vec::with_capacity(capacity));
self.archived = self.archived.push(name,(meta, old_vec));
true
}
fn retrieve(&mut self) -> Option<M> {
if self.current.len() == 0 {
let (meta,v) = self.archived.peek().unwrap();
self.current = v;
self.archived = self.archived.pull().unwrap();
Some(meta)
} else { None }
}
}
impl<E:'static+Debug+Clone+Eq+Hash, M:'static+Debug+Clone+Eq+Hash>
IntoIterator for AStack<E,M> {
type Item = E;
type IntoIter = Iter<E,M>;
fn into_iter(self) -> Self::IntoIter {
Iter(self)
}
}
pub struct Iter<E:'static+Debug+Clone+Eq+Hash, M:'static+Debug+Clone+Eq+Hash>(AStack<E,M>);
impl<E:'static+Debug+Clone+Eq+Hash, M:'static+Debug+Clone+Eq+Hash>
Iterator for Iter<E,M> {
type Item = E;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}
impl<E:'static+Debug+Clone+Eq+Hash>
From<Vec<E>> for AStack<E,()> {
fn from(v: Vec<E>) -> Self {
AStack {
current: v,
archived: Stack::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use adapton::engine::*;
#[test]
fn test_retrieve() {
let mut stack = AStack::new();
stack.push(5);
stack.push(2);
stack.push(3);
let (nums,_) = stack.next_archive().unwrap();
assert_eq!(nums, vec!(5,2,3));
stack.push(4);
stack.push(2);
stack.push(4);
stack.archive(Some(name_of_usize(1)),());
stack.push(9);
stack.push(3);
stack.push(7);
stack.archive(Some(name_of_usize(2)),());
let (nums,_) = stack.next_archive().unwrap();
assert_eq!(nums, vec!());
let (nums,_) = stack.next_archive().unwrap();
assert_eq!(nums, vec!(9,3,7));
let (nums,_) = stack.next_archive().unwrap();
assert_eq!(nums, vec!(4,2,4));
}
#[test]
fn test_through_archive() {
let mut stack = AStack::new();
stack.push(4);
stack.push(2);
stack.push(4);
stack.archive(Some(name_of_usize(1)),());
stack.push(9);
stack.push(3);
assert_eq!(Some(3), stack.pop());
assert_eq!(Some(9), stack.pop());
assert_eq!(Some(4), stack.pop());
assert_eq!(Some(2), stack.pop());
}
#[test]
fn test_peek_archive() {
let mut stack = AStack::new();
stack.push(4);
stack.push(2);
stack.push(4);
stack.archive(Some(name_of_usize(1)),());
stack.push(9);
stack.push(3);
assert_eq!(Some(3), stack.peek());
assert_eq!(Some(3), stack.peek());
stack.pop();
assert_eq!(Some(9), stack.peek());
stack.pop();
assert_eq!(Some(4), stack.peek());
assert_eq!(Some(4), stack.peek());
stack.pop();
stack.pop();
stack.pop();
assert!(stack.is_empty());
}
#[test]
fn test_iter() {
let mut stack = AStack::new();
stack.push(4);
stack.push(2);
stack.push(4);
stack.archive(Some(name_of_usize(1)),());
stack.push(9);
stack.push(3);
stack.push(7);
stack.archive(Some(name_of_usize(2)),());
stack.push(6);
stack.push(1);
stack.push(3);
let as_vec = stack.into_iter().collect::<Vec<_>>();
assert_eq!(vec![3,1,6,7,3,9,4,2,4], as_vec);
}
}