]> git.proxmox.com Git - rustc.git/blobdiff - vendor/generic-array-0.12.4/src/iter.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / vendor / generic-array-0.12.4 / src / iter.rs
diff --git a/vendor/generic-array-0.12.4/src/iter.rs b/vendor/generic-array-0.12.4/src/iter.rs
new file mode 100644 (file)
index 0000000..a2d67fc
--- /dev/null
@@ -0,0 +1,190 @@
+//! `GenericArray` iterator implementation.
+
+use super::{ArrayLength, GenericArray};
+use core::{cmp, ptr, fmt, mem};
+use core::mem::ManuallyDrop;
+
+/// An iterator that moves out of a `GenericArray`
+pub struct GenericArrayIter<T, N: ArrayLength<T>> {
+    // Invariants: index <= index_back <= N
+    // Only values in array[index..index_back] are alive at any given time.
+    // Values from array[..index] and array[index_back..] are already moved/dropped.
+    array: ManuallyDrop<GenericArray<T, N>>,
+    index: usize,
+    index_back: usize,
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    fn send<I: Send>(_iter: I) {}
+
+    #[test]
+    fn test_send_iter() {
+        send(GenericArray::from([1, 2, 3, 4]).into_iter());
+    }
+}
+
+impl<T, N> GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Returns the remaining items of this iterator as a slice
+    #[inline]
+    pub fn as_slice(&self) -> &[T] {
+        &self.array.as_slice()[self.index..self.index_back]
+    }
+
+    /// Returns the remaining items of this iterator as a mutable slice
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        &mut self.array.as_mut_slice()[self.index..self.index_back]
+    }
+}
+
+impl<T, N> IntoIterator for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+    type IntoIter = GenericArrayIter<T, N>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        GenericArrayIter {
+            array: ManuallyDrop::new(self),
+            index: 0,
+            index_back: N::to_usize(),
+        }
+    }
+}
+
+// Based on work in rust-lang/rust#49000
+impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("GenericArrayIter")
+            .field(&self.as_slice())
+            .finish()
+    }
+}
+
+impl<T, N> Drop for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn drop(&mut self) {
+        // Drop values that are still alive.
+        for p in self.as_mut_slice() {
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+    }
+}
+
+// Based on work in rust-lang/rust#49000
+impl<T: Clone, N> Clone for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn clone(&self) -> Self {
+        // This places all cloned elements at the start of the new array iterator,
+        // not at their original indices.
+        unsafe {
+            let mut iter = GenericArrayIter {
+                array: ManuallyDrop::new(mem::uninitialized()),
+                index: 0,
+                index_back: 0,
+            };
+
+            for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) {
+                ptr::write(dst, src.clone());
+
+                iter.index_back += 1;
+            }
+
+            iter
+        }
+    }
+}
+
+impl<T, N> Iterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        if self.index < self.index_back {
+            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
+
+            self.index += 1;
+
+            p
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn nth(&mut self, n: usize) -> Option<T> {
+        // First consume values prior to the nth.
+        let ndrop = cmp::min(n, self.len());
+
+        for p in &mut self.array[self.index..self.index + ndrop] {
+            self.index += 1;
+
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+
+        self.next()
+    }
+
+    fn last(mut self) -> Option<T> {
+        // Note, everything else will correctly drop first as `self` leaves scope.
+        self.next_back()
+    }
+}
+
+impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn next_back(&mut self) -> Option<T> {
+        if self.index < self.index_back {
+            self.index_back -= 1;
+
+            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
+        } else {
+            None
+        }
+    }
+}
+
+impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn len(&self) -> usize {
+        self.index_back - self.index
+    }
+}
+
+// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized
\ No newline at end of file