smart_access/
iter_mut.rs

1//! Support for arbitrary mutating iterators.
2//! __Requires `iter_mut`.__
3//!
4//! This module requires the `alloc` feature: 
5//! our [`Cps`](../trait.Cps.html) values are _affine_ traversals, 
6//! thus they must have 
7//! all the iteration results simultaneously, which in turn requires
8//! allocating memory at runtime.
9//!
10//! This module depends on the [`multiref`](https://crates.io/crates/multiref/) 
11//! crate. The [`Slice`](struct.Slice.html) type is re-exported 
12//! from `multiref`. You can read [the docs](https://docs.rs/multiref/) 
13//! or simply use the `At` impls for `Slice` (they are the same as 
14//! for normal slices).
15//!
16//! ## An example
17//! 
18//! ```
19//! use smart_access::{ Cps, iter_mut::Bounds };
20//! use std::collections::BTreeMap;
21//!
22//! let mut map = BTreeMap::<i32, BTreeMap::<&'static str, i32>>::new();
23//!
24//! map.at( (1, BTreeMap::new()) ).access(|inner| {
25//!     inner.insert("a", 2);
26//!     inner.insert("b", 3);
27//!     inner.insert("c", 4);
28//! });
29//! 
30//! map.at( (5, BTreeMap::new()) ).access(|inner| {
31//!     inner.insert("a", 6);
32//!     inner.insert("b", 7);
33//! });
34//! 
35//! map.at( (8, BTreeMap::new()) ).access(|inner| {
36//!     inner.insert("a", 9);
37//!     inner.insert("x", 10);
38//! });
39//! 
40//! // Hurrah!!! CPS without callback hell!
41//! map.range_mut(5..).map(|(_,v)| v).at(Bounds(..)).at(1).at("a").replace(11);
42//!
43//! assert!(map.at(&8).at("a").get_clone() == Some(11));
44//!
45//! // And now enter batches (and another level of callbacks, 
46//! // but still unlike a typical pyramidal callback hell):
47//! map.range_mut(..=5).map(|(_,v)| v).at(Bounds(..)).batch_ct()
48//!     .add(|x, _| x.at(0).at("c").replace(12))
49//!     .add(|x, _| x.at(0).at("a").replace(13))
50//!     .add(|x, _| x.at(1).at("b").replace(14))
51//!     .run();
52//!
53//! assert!(map.at(&1).at("c").get_clone() == Some(12));
54//! assert!(map.at(&1).at("a").get_clone() == Some(13));
55//! assert!(map.at(&5).at("b").get_clone() == Some(14));
56//! ```
57//!
58//! ## Usage
59//!
60//! Any `Iterator` (exactly `Iterator`, __not__ `IntoIterator`) 
61//! has `At<Bounds<R>>` implemented for every type `R` of `usize`-indexed ranges.
62//!
63//! For example, to access the three elements of a `BTreeMap` with 
64//! the smallest keys, you can write
65//! ```
66//! # use std::collections::BTreeMap;
67//! # use smart_access::{ Cps, iter_mut::Bounds };
68//! # let mut map = BTreeMap::<i32,i32>::new();
69//! # let result =
70//! map.iter_mut().map(|kv| kv.1).at(Bounds(..3)).access( |xs| { /* do something */ } );
71//! # assert!(result == None);
72//! ```
73//!
74//! But the main usecase is to allow indices denoting complex places. Suppose 
75//! that you want to describe a place 
76//! &#8220;every third element of an array&#8221;.
77//!
78//! It can be done with the following code
79//!
80//! ```
81//! # use smart_access::{ At, Cps, iter_mut::{ Bounds, Slice } };
82//! struct EveryThird;
83//!
84//! impl<T> At<EveryThird> for [T] {
85//!     type View = Slice<T>;  // there must be Slice<T> instead of [T]
86//!
87//!     fn access_at<R, F>(&mut self, _: EveryThird, f: F) -> Option<R> where
88//!         F: FnOnce(&mut Slice<T>) -> R
89//!     {
90//!         self.chunks_mut(3)
91//!             .map(|x| unsafe { x.get_unchecked_mut(0) })
92//!             .access_at(Bounds(..), f)  // the key part
93//!     }
94//! }
95//!
96//! // And now the following is possible:
97//! let mut foo = vec![ vec![1, 2, 3, 4], vec![5, 6, 7] ];
98//!
99//! foo.at(0).at(()).at(EveryThird).access(|slice| {
100//!     for x in slice.as_mut() { **x = 8; }
101//! });
102//! assert!(foo == vec![vec![8, 2, 3, 8], vec![5, 6, 7]]);
103//! ```
104
105pub use multiref::Slice;
106mod multiref_impls;
107
108use crate::At;
109
110
111use alloc::vec::Vec;
112
113
114/// A newtype-wrapper around slice bounds.
115#[repr(transparent)]#[derive(Debug,Copy,Clone)]
116pub struct Bounds<B>(pub B);
117
118impl<'a, I, B, V> At<Bounds<B>> for I where
119    I: Iterator<Item=&'a mut V>,
120    [&'a mut V]: At<B, View = [&'a mut V]>,
121    V: 'a + ?Sized,
122{
123    type View = Slice<V>;
124
125    fn access_at<R, F>(&mut self, i: Bounds<B>, f: F) -> Option<R> where
126        F: FnOnce(&mut Slice<V>) -> R
127    {
128        let mut ref_vec = self.collect::<Vec<_>>();
129        // TODO: a more efficient implementation: 
130        // O( len(range) ) instead of O( len(collection) )
131
132        (&mut ref_vec[..]).access_at(i.0, |subslice| {
133            f(Slice::new_mut(subslice))
134        })
135    }
136}