varstack 0.2.4

A call-stack based singly-linked list
Documentation
use core::{clone, cmp, fmt, marker};

use crate::{RefIter, RefStack};

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VarStackEntry<S, V> {
    pub name: S,
    pub value: V,
}

/// Like [`RefStack`], but entries have names
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VarStack<'s, S, V>(pub RefStack<'s, VarStackEntry<S, V>>);

impl<S: Copy + fmt::Debug, V: fmt::Debug> fmt::Debug for VarStack<'_, S, V> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}

impl<'s, S, V> VarStack<'s, S, V> {
    pub fn find(&self, name: &S) -> Option<&V>
    where
        S: cmp::PartialEq,
    {
        let mut this = &self.0;
        while &this.value.name != name {
            this = *this.parent.as_ref()?;
        }
        Some(&this.value.value)
    }

    #[inline(always)]
    pub fn iter(&'s self) -> VarIter<'s, S, V>
    where
        S: Copy,
    {
        VarIter(self.0.iter())
    }
}

impl<'s, S: Copy, V> IntoIterator for &'s VarStack<'s, S, V> {
    type Item = (S, &'s V);
    type IntoIter = VarIter<'s, S, V>;

    #[inline(always)]
    fn into_iter(self) -> VarIter<'s, S, V> {
        VarIter(self.0.iter())
    }
}

pub struct VarIter<'s, S, V>(pub RefIter<'s, VarStackEntry<S, V>>);

impl<S, V> marker::Copy for VarIter<'_, S, V> {}

impl<S, V> clone::Clone for VarIter<'_, S, V> {
    fn clone(&self) -> Self {
        Self(self.0)
    }
}

impl<S: Copy + fmt::Debug, V: fmt::Debug> fmt::Debug for VarIter<'_, S, V> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map().entries(*self).finish()
    }
}

impl<'s, S: Copy, V> Iterator for VarIter<'s, S, V> {
    type Item = (S, &'s V);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|vse| (vse.name, &vse.value))
    }
}