use std::ops::Deref;
use std::rc::Rc;
use std::fmt::{self, Debug};
use std::iter::{IntoIterator, Iterator};
pub trait PushPop<T>
where Self: std::marker::Sized
{
type This;
fn push(&self, val: T) -> Self::This;
fn pop(&self) -> Option<Self::This>;
fn peek(&self) -> Option<&T>;
fn walk(&self) -> StackIterator<T>;
fn depth(&self) -> usize {
self.walk().count()
}
}
struct Cell<T>
where T: Sized
{
value: T,
parent: Option<Rc<Cell<T>>>,
}
impl<T> Cell<T> {
fn orphan(val: T) -> Rc<Self> {
Cell {
value: val,
parent: None,
}
.into()
}
fn with_parent(val: T, parent: Rc<Cell<T>>) -> Rc<Self> {
Cell {
value: val,
parent: Some(parent),
}
.into()
}
}
pub struct Stack<T> {
cell: Rc<Cell<T>>,
}
impl<T> Stack<T> {
pub fn empty() -> Option<Self> {
None
}
pub fn root(val: T) -> Self {
Stack::wrap(Cell::orphan(val))
}
fn wrap(cell: Rc<Cell<T>>) -> Self {
Stack { cell: cell }
}
}
impl<T> PushPop<T> for Stack<T> {
type This = Stack<T>;
fn push(&self, val: T) -> Self {
Stack { cell: Cell::with_parent(val, self.cell.clone()) }
}
fn pop(&self) -> Option<Self> {
self.cell.parent.as_ref().cloned().map(Stack::wrap)
}
fn peek(&self) -> Option<&T> {
Some(self.deref())
}
fn walk(&self) -> StackIterator<T> {
self.into_iter()
}
}
impl<T> PushPop<T> for Option<Stack<T>> {
type This = Stack<T>;
fn push(&self, val: T) -> Self::This {
match *self {
None => Stack::root(val),
Some(ref stack) => stack.push(val),
}
}
fn pop(&self) -> Self {
self.as_ref().and_then(Stack::pop)
}
fn peek(&self) -> Option<&T> {
self.as_ref().and_then(Stack::peek)
}
fn walk(&self) -> StackIterator<T> {
StackIterator { current: self.as_ref().map(|stack| stack.clone()) }
}
}
impl<T> Clone for Stack<T> {
fn clone(&self) -> Stack<T> {
Stack::wrap(self.cell.clone())
}
}
impl<T> Deref for Stack<T> {
type Target = T;
fn deref(&self) -> &T {
&self.cell.deref().value
}
}
impl<T: Debug> Debug for Stack<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "S<{:?}>", **self)
}
}
impl<'a, T> IntoIterator for &'a Stack<T> {
type Item = Stack<T>;
type IntoIter = StackIterator<T>;
fn into_iter(self) -> StackIterator<T> {
StackIterator { current: Some(self.clone()) }
}
}
pub struct StackIterator<T> {
current: Option<Stack<T>>,
}
impl<T> Iterator for StackIterator<T> {
type Item = Stack<T>;
fn next(&mut self) -> Option<Stack<T>> {
let cur = self.current.take();
self.current = cur.as_ref().and_then(Stack::pop);
cur
}
}
impl<T> Stack<T> where T: Default {
pub fn root_default() -> Self {
Stack::root(T::default())
}
pub fn push_default(&self) -> Self {
self.push(T::default())
}
}