]> git.proxmox.com Git - rustc.git/blob - library/alloc/src/vec/drain.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / library / alloc / src / vec / drain.rs
1 use crate::alloc::{Allocator, Global};
2 use core::fmt;
3 use core::iter::{FusedIterator, TrustedLen};
4 use core::mem::{self};
5 use core::ptr::{self, NonNull};
6 use core::slice::{self};
7
8 use super::Vec;
9
10 /// A draining iterator for `Vec<T>`.
11 ///
12 /// This `struct` is created by [`Vec::drain`].
13 /// See its documentation for more.
14 ///
15 /// # Example
16 ///
17 /// ```
18 /// let mut v = vec![0, 1, 2];
19 /// let iter: std::vec::Drain<_> = v.drain(..);
20 /// ```
21 #[stable(feature = "drain", since = "1.6.0")]
22 pub struct Drain<
23 'a,
24 T: 'a,
25 #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global,
26 > {
27 /// Index of tail to preserve
28 pub(super) tail_start: usize,
29 /// Length of tail
30 pub(super) tail_len: usize,
31 /// Current remaining range to remove
32 pub(super) iter: slice::Iter<'a, T>,
33 pub(super) vec: NonNull<Vec<T, A>>,
34 }
35
36 #[stable(feature = "collection_debug", since = "1.17.0")]
37 impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
40 }
41 }
42
43 impl<'a, T, A: Allocator> Drain<'a, T, A> {
44 /// Returns the remaining items of this iterator as a slice.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// let mut vec = vec!['a', 'b', 'c'];
50 /// let mut drain = vec.drain(..);
51 /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
52 /// let _ = drain.next().unwrap();
53 /// assert_eq!(drain.as_slice(), &['b', 'c']);
54 /// ```
55 #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
56 pub fn as_slice(&self) -> &[T] {
57 self.iter.as_slice()
58 }
59
60 /// Returns a reference to the underlying allocator.
61 #[unstable(feature = "allocator_api", issue = "32838")]
62 #[inline]
63 pub fn allocator(&self) -> &A {
64 unsafe { self.vec.as_ref().allocator() }
65 }
66 }
67
68 #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
69 impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> {
70 fn as_ref(&self) -> &[T] {
71 self.as_slice()
72 }
73 }
74
75 #[stable(feature = "drain", since = "1.6.0")]
76 unsafe impl<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {}
77 #[stable(feature = "drain", since = "1.6.0")]
78 unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {}
79
80 #[stable(feature = "drain", since = "1.6.0")]
81 impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
82 type Item = T;
83
84 #[inline]
85 fn next(&mut self) -> Option<T> {
86 self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
87 }
88
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 self.iter.size_hint()
91 }
92 }
93
94 #[stable(feature = "drain", since = "1.6.0")]
95 impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
96 #[inline]
97 fn next_back(&mut self) -> Option<T> {
98 self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
99 }
100 }
101
102 #[stable(feature = "drain", since = "1.6.0")]
103 impl<T, A: Allocator> Drop for Drain<'_, T, A> {
104 fn drop(&mut self) {
105 /// Continues dropping the remaining elements in the `Drain`, then moves back the
106 /// un-`Drain`ed elements to restore the original `Vec`.
107 struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
108
109 impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
110 fn drop(&mut self) {
111 // Continue the same loop we have below. If the loop already finished, this does
112 // nothing.
113 self.0.for_each(drop);
114
115 if self.0.tail_len > 0 {
116 unsafe {
117 let source_vec = self.0.vec.as_mut();
118 // memmove back untouched tail, update to new length
119 let start = source_vec.len();
120 let tail = self.0.tail_start;
121 if tail != start {
122 let src = source_vec.as_ptr().add(tail);
123 let dst = source_vec.as_mut_ptr().add(start);
124 ptr::copy(src, dst, self.0.tail_len);
125 }
126 source_vec.set_len(start + self.0.tail_len);
127 }
128 }
129 }
130 }
131
132 // exhaust self first
133 while let Some(item) = self.next() {
134 let guard = DropGuard(self);
135 drop(item);
136 mem::forget(guard);
137 }
138
139 // Drop a `DropGuard` to move back the non-drained tail of `self`.
140 DropGuard(self);
141 }
142 }
143
144 #[stable(feature = "drain", since = "1.6.0")]
145 impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
146 fn is_empty(&self) -> bool {
147 self.iter.is_empty()
148 }
149 }
150
151 #[unstable(feature = "trusted_len", issue = "37572")]
152 unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {}
153
154 #[stable(feature = "fused", since = "1.26.0")]
155 impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}