[][src]Module smart_access::collections

Implementation of At for some collections. Requires the collections feature.

The following traits are implemented:

  • At<(), View=[T]> for Vec<T>: the slice owned by the vector
  • At<usize, View=T> for Vec<T>: simple indexing
  • At<range, View=Vec<T>> for Vec<T>: subvector (its size can be changed); Warning: access is O(n); consider passing to slices to get O(1) access
  • At<&Q, View=V> for <Some>Map<K,V>: access the value if it is present
  • At<(K,V), View=V> for <Some>Map<K,V>: ensure that the value is present (using the provided default) then access it
  • AT<(K,V,M), View=V> for <Some>Map<K,V>: if the value is present then preprocess it with a mutator M, otherwise insert the provided V
  • AT<&Q, View=T> for <Some>Set<T>: access the value if it is present
  • AT<(T,()), View=T> for <Some>Set<T>: ensure that the value is present then access it
  • AT<(T,), View=<Some>Set<T>> for <Some>Set<T>: ensure that the value is present

Though in normal circumstances these implementations do not panic there exists a possibility of panicking. For example At<range> for Vec<T> splits vector into (at most) three parts then glues them back after the update. Every of these actions can panic on Out Of Memory.

Vector accessors

let mut foo = vec![1,2,3];

assert!(foo.at(0).replace(4) == Some(1));
assert!(foo == vec![4,2,3]);
 
assert!(foo.at(3).replace(0) == None);
assert!(foo == vec![4,2,3]);

assert!(foo.at(1..=2).replace(vec![5,6,7]) == Some(vec![2,3]));
assert!(foo == vec![4,5,6,7]);

// faster but less flexible
//          VVVVVV
assert!(foo.at(()).at(1..=2).at(0).replace(8) == Some(5));
assert!(foo == vec![4,8,6,7]);

Map accessors

Implemented for HashMap and BTreeMap:

  • map.at(&k).access(f) is equivalent to map.get_mut(&k).map(|v| f(v))
  • map.at( (k,v) ).access(f) is equivalent to Some(f(map.entry(k).or_insert(v)))
  • map.at( (k,v,m) ).access(f) is equivalent to Some(f(self.entry(k).and_modify(m).or_insert(v)))
let mut hm = HashMap::<usize, usize>::new();

hm.at( (42, 1) ).touch();

let mut found = false;
hm.at(&42).access(|x| { 
    assert!(*x == 1);

    found = true;
     
    *x += 1; 
});

assert!(found);
assert!(hm.get(&42) == Some(&2));

let mutator = |x: &mut _| { *x = 4; };
hm.at( (41, 3, &mutator) ).touch();
hm.at( (42, 3, &mutator) ).touch();
 
assert!(hm.get(&41) == Some(&3));
assert!(hm.get(&42) == Some(&4));

Set accessors

Implemented for HashSet<T> and BTreeSet<T>.

Semantics differ from the HashMap<T, ()> and BTreeMap<T, ()> implementations: the Map ones do not change the key, but the Set ones do change.

Compare:

let mut map = HashMap::<String,()>::new();
let mut set = HashSet::<String>::new();

map.at( ("Hello".to_string(), ()) ).touch();
set.at( ("Hello".to_string(), ()) ).touch();

map.at("Hello").access(|()| { /* We can do nothing here with the string... */ });
set.at("Hello").access(|hello| { *hello = "world".to_string(); } );

assert!(set == vec!["world".to_string()].into_iter().collect());

Also a one-tuple accessor is available, allowing to chain insertions:

let mut set = HashSet::new();
 
set.at( (2,) ).at( (3,) ).at( (5,) ).at( (7,) ).touch();
assert!(set == vec![2,3,5,7].into_iter().collect());