@@ -55,7 +55,7 @@ extern crate core as std;
5555extern crate alloc;
5656
5757#[ cfg( feature = "use_alloc" ) ]
58- use alloc:: { string:: String , vec:: Vec } ;
58+ use alloc:: { collections :: VecDeque , string:: String , vec:: Vec } ;
5959
6060pub use either:: Either ;
6161
@@ -72,6 +72,8 @@ use std::fmt::Write;
7272use std:: hash:: Hash ;
7373use std:: iter:: { once, IntoIterator } ;
7474#[ cfg( feature = "use_alloc" ) ]
75+ type VecDequeIntoIter < T > = alloc:: collections:: vec_deque:: IntoIter < T > ;
76+ #[ cfg( feature = "use_alloc" ) ]
7577type VecIntoIter < T > = alloc:: vec:: IntoIter < T > ;
7678use std:: iter:: FromIterator ;
7779
@@ -3146,8 +3148,10 @@ pub trait Itertools: Iterator {
31463148
31473149 /// Consumes the iterator and return an iterator of the last `n` elements.
31483150 ///
3149- /// The iterator, if directly collected to a `Vec `, is converted
3151+ /// The iterator, if directly collected to a `VecDeque `, is converted
31503152 /// without any extra copying or allocation cost.
3153+ /// If directly collected to a `Vec`, it may need some data movement
3154+ /// but no re-allocation.
31513155 ///
31523156 /// ```
31533157 /// use itertools::{assert_equal, Itertools};
@@ -3165,20 +3169,22 @@ pub trait Itertools: Iterator {
31653169 /// `.rev().take(n).rev()` to have a similar result (lazy and non-allocating)
31663170 /// without consuming the entire iterator.
31673171 #[ cfg( feature = "use_alloc" ) ]
3168- fn tail ( self , n : usize ) -> VecIntoIter < Self :: Item >
3172+ fn tail ( self , n : usize ) -> VecDequeIntoIter < Self :: Item >
31693173 where
31703174 Self : Sized ,
31713175 {
31723176 match n {
31733177 0 => {
31743178 self . last ( ) ;
3175- Vec :: new ( )
3179+ VecDeque :: new ( )
31763180 }
31773181 1 => self . last ( ) . into_iter ( ) . collect ( ) ,
31783182 _ => {
31793183 // Skip the starting part of the iterator if possible.
31803184 let ( low, _) = self . size_hint ( ) ;
31813185 let mut iter = self . fuse ( ) . skip ( low. saturating_sub ( n) ) ;
3186+ // TODO: If VecDeque has a more efficient method than
3187+ // `.pop_front();.push_back(val)` in the future then maybe revisit this.
31823188 let mut data: Vec < _ > = iter. by_ref ( ) . take ( n) . collect ( ) ;
31833189 // Update `data` cyclically.
31843190 let idx = iter. fold ( 0 , |i, val| {
@@ -3189,7 +3195,8 @@ pub trait Itertools: Iterator {
31893195 i + 1
31903196 }
31913197 } ) ;
3192- // Respect the insertion order.
3198+ // Respect the insertion order, efficiently.
3199+ let mut data = VecDeque :: from ( data) ;
31933200 data. rotate_left ( idx) ;
31943201 data
31953202 }
0 commit comments