use std::collections::BTreeSet;
use std::sync::Arc;
#[derive(Clone, Debug)]
struct Node<K, V> {
key: K,
value: V,
parent: Option<Arc<Node<K, V>>>,
}
#[derive(Debug)]
pub(crate) struct LinkedList<K, V> {
head: Option<Arc<Node<K, V>>>,
}
impl<K, V> Clone for LinkedList<K, V> {
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
}
}
}
impl<K, V> Default for LinkedList<K, V> {
fn default() -> Self {
Self { head: None }
}
}
impl<K, V> LinkedList<K, V> {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn add(&self, key: K, value: V) -> Self {
LinkedList {
head: Some(Arc::new(Node {
key,
value,
parent: self.head.clone(),
})),
}
}
}
impl<K: Eq, V> LinkedList<K, V> {
pub(crate) fn get(&self, key: &K) -> Option<&V> {
let mut current = self.head.as_ref();
while let Some(node) = current {
if &node.key == key {
return Some(&node.value);
}
current = node.parent.as_ref();
}
None
}
}
impl<K: Ord, V> LinkedList<K, V> {
pub(crate) fn iter(&self) -> Iter<'_, K, V> {
Iter {
current: self.head.as_ref(),
seen: BTreeSet::new(),
}
}
}
pub struct Iter<'a, K, V> {
current: Option<&'a Arc<Node<K, V>>>,
seen: BTreeSet<&'a K>,
}
impl<'a, K: Ord, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
loop {
let node = self.current?;
self.current = node.parent.as_ref();
if self.seen.insert(&node.key) {
return Some((&node.key, &node.value));
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_and_iter() {
let l = LinkedList::new().add(1, "a").add(2, "b").add(3, "c");
let v: Vec<_> = l.iter().map(|(k, v)| (*k, *v)).collect();
assert_eq!(v, vec![(3, "c"), (2, "b"), (1, "a")]);
}
#[test]
fn test_persistence() {
let l1 = LinkedList::new().add(1, "a");
let l2 = l1.add(2, "b");
let v1: Vec<_> = l1.iter().map(|(k, v)| (*k, *v)).collect();
assert_eq!(v1, vec![(1, "a")]);
let v2: Vec<_> = l2.iter().map(|(k, v)| (*k, *v)).collect();
assert_eq!(v2, vec![(2, "b"), (1, "a")]);
}
#[test]
fn test_shadowing() {
let l = LinkedList::new().add(1, "a").add(1, "b");
let v: Vec<_> = l.iter().map(|(k, v)| (*k, *v)).collect();
assert_eq!(v, vec![(1, "b")]);
}
#[test]
fn test_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<LinkedList<i32, i32>>();
}
}