smart_access 0.7.0

A minimalistic "lazy bidirectional pointer" framework.
Documentation

use hashbrown::HashMap;
use smart_access::{At, Cps};

struct Ensure<K,V> { key: K, value: V }

impl<V> At<Ensure<usize, V>> for HashMap<usize, V> {
    type View = V;

    fn access_at<R, F>(&mut self, kv: Ensure<usize, V>, f: F) -> Option<R> where
        F: FnOnce(&mut V) -> R
    {
        if let Some(v) = self.get_mut(&kv.key) { 
            return Some(f(v)); 
        } 

        self.insert(kv.key, kv.value);
        Some(f(self.get_mut(&kv.key).unwrap()))
    }
}

fn or_insert<'a, V>(hm: &'a mut HashMap<usize,V>, k: usize, v: V) 
    -> impl Cps<View=V> + 'a 
{
    hm.at(Ensure{ key: k, value: v })
}


#[test]
fn test() {
    let mut hm = HashMap::<usize, String>::new();

    or_insert(&mut hm, 0, String::from("Hello")).touch();
    or_insert(&mut hm, 1, String::from("world")).touch();

    let mut keys = hm.keys().map(|k| k.clone()).collect::<Vec<_>>();
    
    keys.sort();

    let mut answer = String::new();

    for k in keys {
        hm.at(&k).access(|v| { answer.extend(format!("{}", v).chars()); });
    }

    assert_eq!(answer, "Helloworld");
}