]> git.proxmox.com Git - rustc.git/blob - library/alloc/src/vec/drain.rs
New upstream version 1.57.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 #[must_use]
56 #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
57 pub fn as_slice(&self) -> &[T] {
58 self.iter.as_slice()
59 }
60
61 /// Returns a reference to the underlying allocator.
62 #[unstable(feature = "allocator_api", issue = "32838")]
63 #[inline]
64 pub fn allocator(&self) -> &A {
65 unsafe { self.vec.as_ref().allocator() }
66 }
67 }
68
69 #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
70 impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> {
71 fn as_ref(&self) -> &[T] {
72 self.as_slice()
73 }
74 }
75
76 #[stable(feature = "drain", since = "1.6.0")]
77 unsafe impl<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {}
78 #[stable(feature = "drain", since = "1.6.0")]
79 unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {}
80
81 #[stable(feature = "drain", since = "1.6.0")]
82 impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
83 type Item = T;
84
85 #[inline]
86 fn next(&mut self) -> Option<T> {
87 self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
88 }
89
90 fn size_hint(&self) -> (usize, Option<usize>) {
91 self.iter.size_hint()
92 }
93 }
94
95 #[stable(feature = "drain", since = "1.6.0")]
96 impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
97 #[inline]
98 fn next_back(&mut self) -> Option<T> {
99 self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
100 }
101 }
102
103 #[stable(feature = "drain", since = "1.6.0")]
104 impl<T, A: Allocator> Drop for Drain<'_, T, A> {
105 fn drop(&mut self) {
106 /// Continues dropping the remaining elements in the `Drain`, then moves back the
107 /// un-`Drain`ed elements to restore the original `Vec`.
108 struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
109
110 impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
111 fn drop(&mut self) {
112 // Continue the same loop we have below. If the loop already finished, this does
113 // nothing.
114 self.0.for_each(drop);
115
116 if self.0.tail_len > 0 {
117 unsafe {
118 let source_vec = self.0.vec.as_mut();
119 // memmove back untouched tail, update to new length
120 let start = source_vec.len();
121 let tail = self.0.tail_start;
122 if tail != start {
123 let src = source_vec.as_ptr().add(tail);
124 let dst = source_vec.as_mut_ptr().add(start);
125 ptr::copy(src, dst, self.0.tail_len);
126 }
127 source_vec.set_len(start + self.0.tail_len);
128 }
129 }
130 }
131 }
132
133 // exhaust self first
134 while let Some(item) = self.next() {
135 let guard = DropGuard(self);
136 drop(item);
137 mem::forget(guard);
138 }
139
140 // Drop a `DropGuard` to move back the non-drained tail of `self`.
141 DropGuard(self);
142 }
143 }
144
145 #[stable(feature = "drain", since = "1.6.0")]
146 impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
147 fn is_empty(&self) -> bool {
148 self.iter.is_empty()
149 }
150 }
151
152 #[unstable(feature = "trusted_len", issue = "37572")]
153 unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {}
154
155 #[stable(feature = "fused", since = "1.26.0")]
156 impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}