about summary refs log tree commit diff
path: root/library/alloc/src/vec
diff options
context:
space:
mode:
authorC <DeveloperC@protonmail.com>2020-12-05 01:37:10 +0000
committerC <DeveloperC@protonmail.com>2020-12-29 14:03:30 +0000
commitd24a27797df96bb1dbc886f0997138965c5d7b50 (patch)
tree0f969058f8b2e29f283dcc0a96b72a5de800f5b3 /library/alloc/src/vec
parent56d82b3dcc73e227dd2fa4dd4a8ef8d96ce75805 (diff)
downloadrust-d24a27797df96bb1dbc886f0997138965c5d7b50.tar.gz
rust-d24a27797df96bb1dbc886f0997138965c5d7b50.zip
refactor: moving SpecFromIter into spec_from_iter.rs
Diffstat (limited to 'library/alloc/src/vec')
-rw-r--r--library/alloc/src/vec/mod.rs96
-rw-r--r--library/alloc/src/vec/spec_from_iter.rs98
2 files changed, 102 insertions, 92 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 438246ab4cb..dfb837d54f5 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -121,6 +121,10 @@ use self::spec_from_iter_nested::SpecFromIterNested;
 
 mod spec_from_iter_nested;
 
+use self::spec_from_iter::SpecFromIter;
+
+mod spec_from_iter;
+
 /// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
 ///
 /// # Examples
@@ -2156,98 +2160,6 @@ impl<T, A: Allocator> Extend<T> for Vec<T, A> {
     }
 }
 
-/// Specialization trait used for Vec::from_iter
-///
-/// ## The delegation graph:
-///
-/// ```text
-/// +-------------+
-/// |FromIterator |
-/// +-+-----------+
-///   |
-///   v
-/// +-+-------------------------------+  +---------------------+
-/// |SpecFromIter                  +---->+SpecFromIterNested   |
-/// |where I:                      |  |  |where I:             |
-/// |  Iterator (default)----------+  |  |  Iterator (default) |
-/// |  vec::IntoIter               |  |  |  TrustedLen         |
-/// |  SourceIterMarker---fallback-+  |  |                     |
-/// |  slice::Iter                    |  |                     |
-/// |  Iterator<Item = &Clone>        |  +---------------------+
-/// +---------------------------------+
-/// ```
-trait SpecFromIter<T, I> {
-    fn from_iter(iter: I) -> Self;
-}
-
-impl<T, I> SpecFromIter<T, I> for Vec<T>
-where
-    I: Iterator<Item = T>,
-{
-    default fn from_iter(iterator: I) -> Self {
-        SpecFromIterNested::from_iter(iterator)
-    }
-}
-
-impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
-    fn from_iter(iterator: IntoIter<T>) -> Self {
-        // A common case is passing a vector into a function which immediately
-        // re-collects into a vector. We can short circuit this if the IntoIter
-        // has not been advanced at all.
-        // When it has been advanced We can also reuse the memory and move the data to the front.
-        // But we only do so when the resulting Vec wouldn't have more unused capacity
-        // than creating it through the generic FromIterator implementation would. That limitation
-        // is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
-        // But it is a conservative choice.
-        let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
-        if !has_advanced || iterator.len() >= iterator.cap / 2 {
-            unsafe {
-                let it = ManuallyDrop::new(iterator);
-                if has_advanced {
-                    ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
-                }
-                return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
-            }
-        }
-
-        let mut vec = Vec::new();
-        // must delegate to spec_extend() since extend() itself delegates
-        // to spec_from for empty Vecs
-        vec.spec_extend(iterator);
-        vec
-    }
-}
-
-impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
-where
-    I: Iterator<Item = &'a T>,
-    T: Clone,
-{
-    default fn from_iter(iterator: I) -> Self {
-        SpecFromIter::from_iter(iterator.cloned())
-    }
-}
-
-// This utilizes `iterator.as_slice().to_vec()` since spec_extend
-// must take more steps to reason about the final capacity + length
-// and thus do more work. `to_vec()` directly allocates the correct amount
-// and fills it exactly.
-impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
-    #[cfg(not(test))]
-    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
-        iterator.as_slice().to_vec()
-    }
-
-    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
-    // required for this method definition, is not available. Instead use the
-    // `slice::to_vec`  function which is only available with cfg(test)
-    // NB see the slice::hack module in slice.rs for more information
-    #[cfg(test)]
-    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
-        crate::slice::to_vec(iterator.as_slice(), Global)
-    }
-}
-
 // Specialization trait used for Vec::extend
 trait SpecExtend<T, I> {
     fn spec_extend(&mut self, iter: I);
diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs
new file mode 100644
index 00000000000..bf07fc97f89
--- /dev/null
+++ b/library/alloc/src/vec/spec_from_iter.rs
@@ -0,0 +1,98 @@
+use crate::alloc::Global;
+use core::mem::{ManuallyDrop};
+use core::ptr::{self};
+use core::slice::{self};
+
+use super::{Vec, IntoIter, SpecFromIterNested, SpecExtend};
+
+/// Specialization trait used for Vec::from_iter
+///
+/// ## The delegation graph:
+///
+/// ```text
+/// +-------------+
+/// |FromIterator |
+/// +-+-----------+
+///   |
+///   v
+/// +-+-------------------------------+  +---------------------+
+/// |SpecFromIter                  +---->+SpecFromIterNested   |
+/// |where I:                      |  |  |where I:             |
+/// |  Iterator (default)----------+  |  |  Iterator (default) |
+/// |  vec::IntoIter               |  |  |  TrustedLen         |
+/// |  SourceIterMarker---fallback-+  |  |                     |
+/// |  slice::Iter                    |  |                     |
+/// |  Iterator<Item = &Clone>        |  +---------------------+
+/// +---------------------------------+
+/// ```
+pub(super) trait SpecFromIter<T, I> {
+    fn from_iter(iter: I) -> Self;
+}
+
+impl<T, I> SpecFromIter<T, I> for Vec<T>
+    where
+        I: Iterator<Item = T>,
+{
+    default fn from_iter(iterator: I) -> Self {
+        SpecFromIterNested::from_iter(iterator)
+    }
+}
+
+impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
+    fn from_iter(iterator: IntoIter<T>) -> Self {
+        // A common case is passing a vector into a function which immediately
+        // re-collects into a vector. We can short circuit this if the IntoIter
+        // has not been advanced at all.
+        // When it has been advanced We can also reuse the memory and move the data to the front.
+        // But we only do so when the resulting Vec wouldn't have more unused capacity
+        // than creating it through the generic FromIterator implementation would. That limitation
+        // is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
+        // But it is a conservative choice.
+        let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
+        if !has_advanced || iterator.len() >= iterator.cap / 2 {
+            unsafe {
+                let it = ManuallyDrop::new(iterator);
+                if has_advanced {
+                    ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
+                }
+                return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
+            }
+        }
+
+        let mut vec = Vec::new();
+        // must delegate to spec_extend() since extend() itself delegates
+        // to spec_from for empty Vecs
+        vec.spec_extend(iterator);
+        vec
+    }
+}
+
+impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
+    where
+        I: Iterator<Item = &'a T>,
+        T: Clone,
+{
+    default fn from_iter(iterator: I) -> Self {
+        SpecFromIter::from_iter(iterator.cloned())
+    }
+}
+
+// This utilizes `iterator.as_slice().to_vec()` since spec_extend
+// must take more steps to reason about the final capacity + length
+// and thus do more work. `to_vec()` directly allocates the correct amount
+// and fills it exactly.
+impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
+    #[cfg(not(test))]
+    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
+        iterator.as_slice().to_vec()
+    }
+
+    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
+    // required for this method definition, is not available. Instead use the
+    // `slice::to_vec`  function which is only available with cfg(test)
+    // NB see the slice::hack module in slice.rs for more information
+    #[cfg(test)]
+    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
+        crate::slice::to_vec(iterator.as_slice(), Global)
+    }
+}