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