use std::sync::Arc;
#[derive(Debug)]
pub struct Stack<T: 'static>(Link<'static, T>);
impl<T> Default for Stack<T> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T> FromIterator<T> for Stack<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut list = Stack::new();
for item in iter {
list += item;
}
list
}
}
impl<T> core::ops::Add<T> for Stack<T> {
type Output = Self;
fn add(self, item: T) -> Self::Output {
Self(Link::Own(Arc::new(Entry {
item,
next: self.0.clone(),
})))
}
}
impl<T> core::ops::Add<T> for &Stack<T> {
type Output = Stack<T>;
fn add(self, item: T) -> Self::Output {
Stack(Link::Own(Arc::new(Entry {
item,
next: self.0.clone(),
})))
}
}
impl<T> core::ops::AddAssign<T> for Stack<T> {
fn add_assign(&mut self, rhs: T) {
*self = core::mem::take(self) + rhs
}
}
impl<'a, T> Stack<T> {
pub fn new() -> Self {
Self(Link::Empty)
}
pub fn iter(&'a self) -> impl 'a + Iterator<Item = &'a T> {
&self.0
}
pub(crate) fn head(&self) -> Option<&T> {
self.0.as_ref().map(|e| &e.item)
}
}
#[derive(Debug)]
enum Link<'a, T> {
Empty,
Ref(&'a Entry<'a, T>),
Own(Arc<Entry<'a, T>>),
}
impl<'a, T> Link<'a, T> {
fn as_ref(&'a self) -> Option<&'a Entry<'a, T>> {
Some(match self {
Link::Empty => return None,
Link::Ref(entry) => entry,
Link::Own(entry) => entry.as_ref(),
})
}
}
impl<T> Default for Link<'_, T> {
fn default() -> Self {
Self::Empty
}
}
impl<T> Clone for Link<'_, T> {
fn clone(&self) -> Self {
match self {
Self::Empty => Self::Empty,
Self::Ref(entry) => Self::Ref(entry),
Self::Own(entry) => Self::Own(entry.clone()),
}
}
}
#[derive(Debug, Default)]
struct Entry<'a, T> {
item: T,
next: Link<'a, T>,
}
impl<'a, T> Iterator for &'a Link<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let entry = match self {
Link::Empty => return None,
Link::Ref(entry) => entry,
Link::Own(entry) => entry.as_ref(),
};
*self = &entry.next;
Some(&entry.item)
}
}
#[cfg(test)]
mod tests {
use super::Stack;
#[test]
fn add() {
let stack = Stack::new() + true + false;
assert_eq!(stack.iter().collect::<Vec<_>>(), vec![&false, &true]);
}
#[test]
fn add_assign() {
let mut stack = Stack::new();
stack += "a";
stack += "b";
assert_eq!(stack.iter().collect::<Vec<_>>(), vec![&"b", &"a"]);
}
#[test]
fn collect() {
let stack = [1, 2, 3].into_iter().collect::<Stack<usize>>();
assert_eq!(stack.iter().collect::<Vec<_>>(), vec![&3, &2, &1]);
}
}