diff options
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/arc.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/binary_heap.rs | 6 | ||||
| -rw-r--r-- | src/liballoc/boxed.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/btree/map.rs | 14 | ||||
| -rw-r--r-- | src/liballoc/btree/node.rs | 14 | ||||
| -rw-r--r-- | src/liballoc/linked_list.rs | 4 | ||||
| -rw-r--r-- | src/liballoc/raw_vec.rs | 14 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/slice.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/string.rs | 61 | ||||
| -rw-r--r-- | src/liballoc/tests/lib.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/tests/string.rs | 20 | ||||
| -rw-r--r-- | src/liballoc/tests/vec.rs | 167 | ||||
| -rw-r--r-- | src/liballoc/vec.rs | 117 | ||||
| -rw-r--r-- | src/liballoc/vec_deque.rs | 2 |
15 files changed, 391 insertions, 38 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index daf556795fa..b967eaaaab5 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -278,7 +278,7 @@ impl<T> Arc<T> { let x: Box<_> = box ArcInner { strong: atomic::AtomicUsize::new(1), weak: atomic::AtomicUsize::new(1), - data: data, + data, }; Arc { ptr: Shared::from(Box::into_unique(x)) } } diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 988f8851625..57640af816a 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -853,9 +853,9 @@ impl<'a, T> Hole<'a, T> { debug_assert!(pos < data.len()); let elt = ptr::read(&data[pos]); Hole { - data: data, + data, elt: Some(elt), - pos: pos, + pos, } } @@ -1203,7 +1203,7 @@ where T: Clone + Ord { let place = Placer::make_place(self.data.place_back()); BinaryHeapPlace { heap: ptr, - place: place, + place, } } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 17dc3d03aae..26692b6e3da 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -169,7 +169,7 @@ fn make_place<T>() -> IntermediateBox<T> { IntermediateBox { ptr: p, - layout: layout, + layout, marker: marker::PhantomData, } } diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index a51c70159db..f733c3332e2 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -234,7 +234,7 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()> match search::search_tree(self.root.as_mut(), key) { Found(handle) => { Some(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, } @@ -250,8 +250,8 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()> Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), GoDown(handle) => { VacantEntry { - key: key, - handle: handle, + key, + handle, length: &mut self.length, _marker: PhantomData, } @@ -695,7 +695,7 @@ impl<K: Ord, V> BTreeMap<K, V> { match search::search_tree(self.root.as_mut(), key) { Found(handle) => { Some(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, } @@ -866,15 +866,15 @@ impl<K: Ord, V> BTreeMap<K, V> { match search::search_tree(self.root.as_mut(), &key) { Found(handle) => { Occupied(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, }) } GoDown(handle) => { Vacant(VacantEntry { - key: key, - handle: handle, + key, + handle, length: &mut self.length, _marker: PhantomData, }) diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs index 0e61905131f..b057c18fca8 100644 --- a/src/liballoc/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -776,8 +776,8 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar debug_assert!(idx < node.len()); Handle { - node: node, - idx: idx, + node, + idx, _marker: PhantomData } } @@ -850,8 +850,8 @@ impl<BorrowType, K, V, NodeType> debug_assert!(idx <= node.len()); Handle { - node: node, - idx: idx, + node, + idx, _marker: PhantomData } } @@ -1149,7 +1149,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: let mut new_root = Root { node: BoxedNode::from_internal(new_node), - height: height + height, }; for i in 0..(new_len+1) { @@ -1449,12 +1449,12 @@ impl<BorrowType, K, V, HandleType> > { match self.node.force() { ForceResult::Leaf(node) => ForceResult::Leaf(Handle { - node: node, + node, idx: self.idx, _marker: PhantomData }), ForceResult::Internal(node) => ForceResult::Internal(Handle { - node: node, + node, idx: self.idx, _marker: PhantomData }) diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index 850dd6adcf0..f9512cbe977 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -140,7 +140,7 @@ impl<T> Node<T> { Node { next: None, prev: None, - element: element, + element, } } @@ -924,7 +924,7 @@ impl<'a, T> IterMut<'a, T> { let node = Some(Shared::from(Box::into_unique(box Node { next: Some(head), prev: Some(prev), - element: element, + element, }))); prev.as_mut().next = node; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 6090fc3942a..9a8614895f3 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -60,8 +60,8 @@ impl<T, A: Alloc> RawVec<T, A> { // Unique::empty() doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::empty(), - cap: cap, - a: a, + cap, + a, } } @@ -104,8 +104,8 @@ impl<T, A: Alloc> RawVec<T, A> { RawVec { ptr: Unique::new_unchecked(ptr as *mut _), - cap: cap, - a: a, + cap, + a, } } } @@ -159,8 +159,8 @@ impl<T, A: Alloc> RawVec<T, A> { pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap: cap, - a: a, + cap, + a, } } } @@ -176,7 +176,7 @@ impl<T> RawVec<T, Heap> { pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap: cap, + cap, a: Heap, } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a2184054b37..9783aed895f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -311,7 +311,7 @@ impl<T> Rc<T> { ptr: Shared::from(Box::into_unique(box RcBox { strong: Cell::new(1), weak: Cell::new(1), - value: value, + value, })), } } diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index ec7a2b6d0e8..356ca7a5f5e 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1886,7 +1886,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F) // Push this run onto the stack. runs.push(Run { - start: start, + start, len: end - start, }); end = start; diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 3ed5d2df1ab..76ee0158a62 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1061,6 +1061,57 @@ impl String { ch } + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place and preserves the order of the retained + /// characters. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_retain)] + /// + /// let mut s = String::from("f_o_ob_ar"); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + #[inline] + #[unstable(feature = "string_retain", issue = "43874")] + pub fn retain<F>(&mut self, mut f: F) + where F: FnMut(char) -> bool + { + let len = self.len(); + let mut del_bytes = 0; + let mut idx = 0; + + while idx < len { + let ch = unsafe { + self.slice_unchecked(idx, len).chars().next().unwrap() + }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + del_bytes += ch_len; + } else if del_bytes > 0 { + unsafe { + ptr::copy(self.vec.as_ptr().offset(idx as isize), + self.vec.as_mut_ptr().offset((idx - del_bytes) as isize), + ch_len); + } + } + + // Point idx to the next char + idx += ch_len; + } + + if del_bytes > 0 { + unsafe { self.vec.set_len(len - del_bytes); } + } + } + /// Inserts a character into this `String` at a byte position. /// /// This is an `O(n)` operation as it requires copying every element in the @@ -1327,8 +1378,8 @@ impl String { let chars_iter = self[start..end].chars(); Drain { - start: start, - end: end, + start, + end, iter: chars_iter, string: self_ptr, } @@ -1391,11 +1442,11 @@ impl String { let chars_iter = self[start..end].chars(); Splice { - start: start, - end: end, + start, + end, iter: chars_iter, string: self_ptr, - replace_with: replace_with + replace_with, } } diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 27b23d14059..86309dd87de 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -16,6 +16,7 @@ #![feature(inclusive_range_syntax)] #![feature(collection_placement)] #![feature(const_fn)] +#![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(iterator_step_by)] #![feature(pattern)] @@ -25,6 +26,7 @@ #![feature(slice_rotate)] #![feature(splice)] #![feature(str_escape)] +#![feature(string_retain)] #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index b1731b2a5dc..f5c124c6b44 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -333,6 +333,26 @@ fn remove_bad() { } #[test] +fn test_retain() { + let mut s = String::from("α_β_γ"); + + s.retain(|_| true); + assert_eq!(s, "α_β_γ"); + + s.retain(|c| c != '_'); + assert_eq!(s, "αβγ"); + + s.retain(|c| c != 'β'); + assert_eq!(s, "αγ"); + + s.retain(|c| c == 'α'); + assert_eq!(s, "α"); + + s.retain(|_| false); + assert_eq!(s, ""); +} + +#[test] fn insert() { let mut s = "foobar".to_string(); s.insert(0, 'ệ'); diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 17f1229c206..670ea8089fc 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -801,3 +801,170 @@ fn overaligned_allocations() { assert!(v.as_ptr() as usize & 0xff == 0); } } + +#[test] +fn drain_filter_empty() { + let mut vec: Vec<i32> = vec![]; + + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut vec = vec![(), (), (), (), ()]; + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_false() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(vec.len(), initial_len); + assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_complex() { + + { // [+xxx++++++xxxxx++++x+x++] + let mut vec = vec![1, + 2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 14); + assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { // [xxx++++++xxxxx++++x+x++] + let mut vec = vec![2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 13); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { // [xxx++++++xxxxx++++x+x] + let mut vec = vec![2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 11); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]); + } + + { // [xxxxxxxxxx+++++++++++] + let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { // [+++++++++++xxxxxxxxxx] + let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, + 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + + diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5f68e59289d..8141851b8c9 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1728,9 +1728,9 @@ impl<T> IntoIterator for Vec<T> { mem::forget(self); IntoIter { buf: Shared::new_unchecked(begin), - cap: cap, + cap, ptr: begin, - end: end, + end, } } } @@ -1960,6 +1960,65 @@ impl<T> Vec<T> { } } + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, it will try again, and call the closure + /// on the next element, seeing if it passes the test. + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 }; + /// # let mut vec = vec![1, 2, 3, 4, 5]; + /// let mut i = 0; + /// while i != vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } + /// i += 1; + /// } + /// ``` + /// + /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `drain_filter` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(drain_filter)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<T, F> + where F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { self.set_len(0); } + + DrainFilter { + vec: self, + idx: 0, + del: 0, + old_len, + pred: filter, + } + } } /// Extend implementation that copies elements out of references before pushing them onto the Vec. @@ -2602,3 +2661,57 @@ impl<'a, T> Drain<'a, T> { self.tail_start = new_tail_start; } } + +/// An iterator produced by calling `drain_filter` on Vec. +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter<'a, T: 'a, F> + where F: FnMut(&mut T) -> bool, +{ + vec: &'a mut Vec<T>, + idx: usize, + del: usize, + old_len: usize, + pred: F, +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T, F> Iterator for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + unsafe { + while self.idx != self.old_len { + let i = self.idx; + self.idx += 1; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + if (self.pred)(&mut v[i]) { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + v.swap(i - self.del, i); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T, F> Drop for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + for _ in self.by_ref() { } + + unsafe { + self.vec.set_len(self.old_len - self.del); + } + } +} diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 2068c2c9c5f..bf906920029 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -2442,7 +2442,7 @@ impl<T> From<Vec<T>> for VecDeque<T> { VecDeque { tail: 0, head: len, - buf: buf, + buf, } } } |
