subset/unique/
mod.rs

1//! Subset of slice's items that is able to iterate forward and backward over mutable or immutable references to selected items.
2//! Each item of a slice can be selected no more than once.
3//! 
4//! # Examples
5//!
6//! ```
7//! use subset::unique::*;
8//! 
9//! // Constructing mutable subset
10//! let mut set = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
11//! let idxs = vec![10];
12//! assert_eq!(SubsetMut::new(&mut set, &idxs).err(), Some(SubsetError::OutOfBounds));
13//! let idxs = vec![2, 2, 5];
14//! assert_eq!(SubsetMut::new(&mut set, &idxs).err(), Some(SubsetError::NotUnique));
15//! let idxs = vec![2, 4, 7];   // Indexes of selected items
16//! let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
17//! 
18//! // Iterating over mutable references
19//! let mut iter = subset.iter_mut();
20//! let r1 = iter.next().unwrap();
21//! assert_eq!(*r1, 7);
22//! let r2 = iter.next().unwrap();
23//! assert_eq!(*r2, 5);
24//! *r1 = 19;
25//! *r2 = 33;
26//! assert_eq!(iter.next(), Some(&mut 2));
27//! assert_eq!(iter.next(), None);
28//! assert_eq!(subset.set(), vec![9, 8, 19, 6, 33, 4, 3, 2, 1, 0].as_slice());
29//! 
30//! // Converting to immutable subset
31//! let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
32//! let imm_subset: Subset<_> = subset.into();
33//! 
34//! // Converting to mutable or immutable multi-subset
35//! let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
36//! let multi_subset: subset::multi::SubsetMut<_> = subset.into();
37//! let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
38//! let imm_multi_subset: subset::multi::Subset<_> = subset.into();
39//! ```
40
41pub use std::convert::{From,Into,TryFrom,TryInto};
42use super::{is_unique, multi};
43pub use super::SubsetError;
44
45/// Subset of slice's items that is able to iterate forward and backward over immutable references to selected items.
46/// Each item of a slice can be selected no more than once.
47// Just a wrapper over multi::Subset
48#[derive(Debug)]
49pub struct Subset<'a, T> {
50    pub(crate) m: multi::Subset<'a, T>
51}
52
53
54impl<'a, T> Subset<'a, T> {
55    /// Constructs a subset from the whole set and indexes of the selected items.
56    /// Both the uniqueness of the selected items and the array bounds is checked.
57    /// Note that subsets are not designed for ZSTs.
58    /// 
59    /// # Examples
60    /// 
61    /// ```
62    /// # use subset::unique::*;
63    /// let set = [1.0, 1.1, 1.2];
64    /// let idxs = [0, 1];
65    /// let subset = Subset::new(&set, &idxs).unwrap();
66    /// ```
67    /// 
68    /// # Errors
69    /// NotUnique, if there are duplicate indexes.
70    /// OutOfBounds, if any index is `>= set.len()`.
71    /// 
72    /// # Panics
73    /// Panics if `std::mem::size_of::<T>() == 0`
74    pub fn new(set: &'a [T], idxs: &'a [usize]) -> Result<Self, SubsetError> {
75        multi::Subset::new(set, idxs)?.try_into()
76    }
77    /// Constructs a subset from the whole set and indexes of the selected items.
78    /// Neither the uniqueness of the selected items, nor the array bounds is checked.
79    pub unsafe fn new_unchecked(set: &'a [T], idxs: &'a [usize]) -> Self {
80        multi::Subset::new_unchecked(set, idxs).to_unique_unchecked()
81    }
82    /// Returns the original slice.
83    pub fn set(&self) -> &[T] {
84        self.m.set()
85    }
86    /// Returns indexes of selected items.
87    pub fn idxs(&self) -> &[usize] {
88        self.m.idxs()
89    }
90    /// Returns an iterator over immutable references to selected items.
91    pub fn iter(&self) -> multi::Iter<T> {
92        self.m.iter()
93    }
94}
95
96
97impl<'a, T> From<SubsetMut<'a, T>> for Subset<'a, T> {
98    fn from(s: SubsetMut<'a, T>) -> Self {
99        Self {
100            m: s.m.into()
101        }
102    }
103}
104
105
106impl<'a, T> TryFrom<multi::Subset<'a, T>> for Subset<'a, T> {
107    type Error = SubsetError;
108    fn try_from(s: multi::Subset<'a, T>) -> Result<Self, SubsetError> {
109        if is_unique(s.idxs) {
110            Ok(unsafe{s.to_unique_unchecked()})
111        } else {
112            Err(SubsetError::NotUnique)
113        }
114    }
115}
116
117
118impl<'a, T> TryFrom<multi::SubsetMut<'a, T>> for Subset<'a, T> {
119    type Error = SubsetError;
120    fn try_from(s: multi::SubsetMut<'a, T>) -> Result<Self, SubsetError> {
121        if is_unique(s.idxs) {
122            Ok(unsafe{s.to_unique_unchecked()})
123        } else {
124            Err(SubsetError::NotUnique)
125        }
126    }
127}
128
129
130impl<'a, T> IntoIterator for &'a Subset<'a, T> {
131    type Item = &'a T;
132    type IntoIter = multi::Iter<'a, T>;
133    fn into_iter(self) -> multi::Iter<'a, T> {
134        self.iter()
135    }
136}
137
138
139/// Subset of slice's items that is able to iterate forward and backward over mutable or immutable references to selected items.
140/// Each item of a slice can be selected no more than once.
141// Just a wrapper over multi::SubsetMut
142#[derive(Debug)]
143pub struct SubsetMut<'a, T> {
144    pub(crate) m: multi::SubsetMut<'a, T>
145}
146
147/// Double-ended iterator over mutable references to selected items of set.
148pub struct IterMut<'a, T> {
149    ptr: *mut T,    // Points to the set
150    iter: std::slice::Iter<'a, usize>
151}
152
153impl<'a, T> SubsetMut<'a, T> {
154    /// Constructs a subset from the whole set and indexes of the selected items.
155    /// Both the uniqueness of the selected items and the array bounds is checked.
156    /// Note that subsets are not designed for ZSTs.
157    /// 
158    /// # Examples
159    /// 
160    /// ```
161    /// # use subset::unique::*;
162    /// let mut set = [1.0, 1.1, 1.2];
163    /// let idxs = [0, 1];
164    /// let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
165    /// subset.set()[0] = 3.1415;
166    /// ```
167    /// 
168    /// # Errors
169    /// NotUnique, if there are duplicate indexes.
170    /// OutOfBounds, if any index is `>= set.len()`.
171    /// 
172    /// # Panics
173    /// Panics if `std::mem::size_of::<T>() == 0`
174    pub fn new(set: &'a mut [T], idxs: &'a [usize]) -> Result<Self, SubsetError> {
175        multi::SubsetMut::new(set, idxs)?.try_into()
176    }
177    /// Constructs a subset from the whole set and indexes of the selected items.
178    /// Neither the uniqueness of the selected items, nor the array bounds is checked.
179    pub unsafe fn new_unchecked(set: &'a mut [T], idxs: &'a [usize]) -> Self {
180        multi::SubsetMut::new_unchecked(set, idxs).to_unique_mut_unchecked()
181    }
182    /// Returns the original slice.
183    pub fn set(&mut self) -> &mut [T] {
184        self.m.set()
185    }
186    /// Returns indexes of selected items.
187    pub fn idxs(&self) -> &[usize] {
188        self.m.idxs()
189    }
190    /// Returns an iterator over immutable references to selected items.
191    pub fn iter(&self) -> multi::Iter<T> {
192        self.m.iter()
193    }
194    /// Returns an iterator over mutable references to selected items.
195    pub fn iter_mut(&mut self) -> IterMut<T> {
196        IterMut {
197            ptr: self.m.set.as_mut_ptr(),
198            iter: self.m.idxs.iter()
199        }
200    }
201}
202
203
204impl<'a, T> TryFrom<multi::SubsetMut<'a, T>> for SubsetMut<'a, T> {
205    type Error = SubsetError;
206    fn try_from(s: multi::SubsetMut<'a, T>) -> Result<Self, SubsetError> {
207        if is_unique(s.idxs) {
208            Ok(unsafe{s.to_unique_mut_unchecked()})
209        } else {
210            Err(SubsetError::NotUnique)
211        }
212    }
213}
214
215
216impl<'a, T: 'a> Iterator for IterMut<'a, T> {
217    type Item = &'a mut T;
218    fn next(&mut self) -> Option<&'a mut T> {
219        unsafe {
220            match self.iter.next() {
221                None => None,
222                Some(idx) => Some(&mut *self.ptr.offset(*idx as isize))
223            }
224        }
225    }
226}
227
228
229impl<'a, T: 'a> DoubleEndedIterator for IterMut<'a, T> {
230    fn next_back(&mut self) -> Option<&'a mut T> {
231        unsafe {
232            match self.iter.next_back() {
233                None => None,
234                Some(idx) => Some(&mut *self.ptr.offset(*idx as isize))
235            }
236        }
237    }
238}
239
240
241impl<'a, T> IntoIterator for &'a SubsetMut<'a, T> {
242    type Item = &'a T;
243    type IntoIter = multi::Iter<'a, T>;
244    fn into_iter(self) -> multi::Iter<'a, T> {
245        self.iter()
246    }
247}
248
249
250impl<'a, T> IntoIterator for &'a mut SubsetMut<'a, T> {
251    type Item = &'a mut T;
252    type IntoIter = IterMut<'a, T>;
253    fn into_iter(self) -> IterMut<'a, T> {
254        self.iter_mut()
255    }
256}
257
258
259
260#[cfg(test)]
261mod tests {
262
263    use super::*;
264
265    #[test]
266    fn test_set() {
267        let set = vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
268        let idxs = vec![2, 2];
269        assert_eq!(Subset::new(&set, &idxs).err(), Some(SubsetError::NotUnique));
270        let idxs = vec![10];
271        assert_eq!(Subset::new(&set, &idxs).err(), Some(SubsetError::OutOfBounds));
272        let idxs = vec![2, 4, 7];
273        let subset = Subset::new(&set, &idxs).unwrap();
274        let mut sum = 0;
275        for e in subset.iter() {
276            sum += e;
277        }
278        assert_eq!(sum, 14);
279        let mut sum = 0;
280        for e in subset.iter().map(|v| 2*v).rev() {
281            sum += e;
282        }
283        assert_eq!(sum, 28);
284    }
285
286    #[test]
287    fn test_mut() {
288        let mut set = vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
289        let idxs = vec![2, 2];
290        assert_eq!(SubsetMut::new(&mut set, &idxs).err(), Some(SubsetError::NotUnique));
291        let idxs = vec![10];
292        assert_eq!(SubsetMut::new(&mut set, &idxs).err(), Some(SubsetError::OutOfBounds));
293        let idxs = vec![2, 4, 7];
294        let mut subset = SubsetMut::new(&mut set, &idxs).unwrap();
295        let mut iter = subset.iter_mut();
296        let r1 = iter.next().unwrap();
297        let r2 = iter.next().unwrap();
298        *r1 = 19;
299        *r2 = 33;
300        assert_eq!(subset.set(), vec![9, 8, 19, 6, 33, 4, 3, 2, 1, 0].as_slice());
301        let mut sum = 0;
302        for e in subset.iter().map(|v| 2* *v).rev() {
303            sum += e;
304        }
305        assert_eq!(sum, 108);
306        let result_into: crate::multi::SubsetMut<_> = subset.into();
307        assert!(result_into.is_unique());
308        assert_eq!(result_into.iter().fold(0, |accum, v| accum + *v), 54);
309    }
310}