├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── index.html └── src ├── benches.rs ├── lib.rs ├── sliding_windows.rs └── tests.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target/debug 2 | target/release 3 | target/package 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ================= 3 | 4 | ### 3.0 5 | This release breaks the old API in favour of huge performance gains. Before 3.0 it was 6 | possible to deref a Window into a slice of T. This made it necessary to place the 7 | elements of the wrapped Iterator sequentially in memory. So one had to either allocate 8 | a lot of memory or copy a lot. 9 | 10 | This is no longer the case. The new API includes 2 Iterators (over &T and &mut T) 11 | for Window. This makes it possible to avoid copying **ENTIRELY**. 12 | 13 | - Remove Storage::new_exact and Storage::optimized, they are no longer needed 14 | - Remove impl of Deref/DerefMut for Window 15 | - Add WindowIter/WindowIterMut instead 16 | - Add CHANGELOG.md 17 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sliding_windows" 3 | description = "a non-copying implementation of a sliding windows iterator adaptor" 4 | version = "3.0.0" 5 | authors = ["flo-l "] 6 | license = "MIT" 7 | homepage = "https://docs.rs/sliding_windows/" 8 | documentation = "https://docs.rs/sliding_windows/" 9 | repository = "https://github.com/flo-l/rust-sliding_windows/" 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Florian Lackner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sliding_windows 2 | =============== 3 | 4 | This crate offers an ```Iterator``` adaptor, which yields "sliding windows" over the elements returned by the wrapped iterator. 5 | 6 | It's worth to note that it does **not** copy elements, which makes the code several orders of mignitudes faster than naive copying variants. 7 | 8 | As a consequence it violates the Iterator protocol slightly. It is not possible to have two Windows into the data 9 | available at the same time. This is checked during runtime. 10 | 11 | The backing storage is a ```Vec```, so this Iterator adaptor is not ideal for very large windows (>20 elements or very huge elements). 12 | 13 | I'd happily accept a PR to implement the same functionality with a ```VecDeque``` or similar, see this [issue](https://github.com/flo-l/rust-sliding_windows/issues/2). 14 | 15 | ### Links 16 | 17 | - [Documentation](https://docs.rs/sliding_windows/) 18 | - [crates.io](https://crates.io/crates/sliding_windows) 19 | 20 | ### Install 21 | 22 | Add this to your ```Cargo.toml```. 23 | 24 | [dependencies] 25 | sliding_windows = "3.0" 26 | 27 | ### Example 28 | 29 | ```rust 30 | extern crate sliding_windows; 31 | use sliding_windows::{IterExt, Storage}; 32 | 33 | fn main() { 34 | let mut storage: Storage = Storage::new(3); 35 | 36 | for x in (0..5).sliding_windows(&mut storage) { 37 | println!("{:?}", x); 38 | } 39 | } 40 | 41 | // This outputs: 42 | // Window[0, 1, 2] 43 | // Window[1, 2, 3] 44 | // Window[2, 3, 4] 45 | ``` 46 | 47 | For more examples please consult the [Documentation](https://docs.rs/sliding_windows/). 48 | 49 | ### This functionality in other languages/crates 50 | 51 | - Ruby: [#each_cons](http://ruby-doc.org/core-2.1.0/Enumerable.html#method-i-each_cons) 52 | - Python: [window](https://docs.python.org/release/2.3.5/lib/itertools-example.html) 53 | - Rust (just for slices): [.windows()](https://doc.rust-lang.org/std/primitive.slice.html#method.windows) 54 | - Rust (for all Iterators, but copying): [.slide()](https://github.com/slapresta/rust-iterslide) 55 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/benches.rs: -------------------------------------------------------------------------------- 1 | use test::test::Bencher; 2 | use super::*; 3 | 4 | #[bench] 5 | fn sliding_windows(b: &mut Bencher) { 6 | let num = 12; 7 | let data: &[u8] = &[num; 1024*1024]; 8 | let mut storage: Storage<&u8> = Storage::new(10); 9 | 10 | b.iter(|| { 11 | let data = test::black_box(&data); 12 | let storage = test::black_box(&mut storage); 13 | 14 | let iter = Adaptor::new(data.iter(), storage); 15 | 16 | for window in iter { 17 | for x in window.iter() { 18 | let x: &u8 = test::black_box(x); 19 | assert_eq!(*x, num) 20 | } 21 | } 22 | }); 23 | } 24 | 25 | #[bench] 26 | fn slice_window(b: &mut Bencher) { 27 | let num = 12; 28 | let data: &[u8] = &[num; 1024*1024]; 29 | 30 | b.iter(|| { 31 | let data = test::black_box(&data); 32 | let iter = data.windows(10); 33 | for window in iter { 34 | for x in window.iter() { 35 | let x: &u8 = test::black_box(x); 36 | assert_eq!(*x, num) 37 | } 38 | } 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides an iterator adaptor that yields sliding windows into the elements of the wrapped Iterator. 2 | //! 3 | //! Note that this adaptor does **NEVER** clone any element for huge speed gains. 4 | //! 5 | //! As a consequence it violates the Iterator protocol slightly. It is not possible to have two Windows into the data 6 | //! available at the same time. This is checked during runtime. If this check fails, the Adaptor panicks in ```next()```. 7 | //! More information can be found in the section [Panics](#panics). 8 | //! 9 | //! There are some options regarding the constructor for Storage, which allow reuse of an allocation. 10 | //! Consult the [docs for Storage](struct.Storage.html) for details. 11 | //! 12 | //! Iterator element type is `Window<'a, Self::Item>`. 13 | //! 14 | //! Note: `Window<'a, Self::Item>` implements `iter()` and `iter_mut()`, which return Iterators over the elements of the `Window`. 15 | //! 16 | //! This iterator is *fused*. 17 | //! 18 | //! # Example: 19 | //! 20 | //! ``` 21 | //! use sliding_windows::IterExt; 22 | //! use sliding_windows::Storage; 23 | //! 24 | //! let iter = 0..5; 25 | //! let mut storage: Storage = Storage::new(3); 26 | //! let windowed_iter = iter.sliding_windows(&mut storage); 27 | //! let output: Vec> = windowed_iter.map(|x| x.iter().map(|&x| x).collect()).collect(); 28 | //! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]]; 29 | //! 30 | //! assert_eq!(output, expected); 31 | //! ``` 32 | //! 33 | //! It's also possible to reuse an allocation for `Storage` via the `Into` trait. 34 | //! 35 | //! # Example: 36 | //! 37 | //! ``` 38 | //! use sliding_windows::IterExt; 39 | //! use sliding_windows::Storage; 40 | //! 41 | //! let previous_alloca = vec![0u32; 3]; // length doesn't have to be equal to window_size 42 | //! let mut storage: Storage = Storage::from_vec(previous_alloca, 3); 43 | //! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]]; 44 | //! 45 | //! // extra scope so that windowed_iter doesn't outlive storage.into() call 46 | //! { 47 | //! let windowed_iter = (0..5).sliding_windows(&mut storage); 48 | //! let output: Vec> = windowed_iter.map(|x| x.iter().map(|&x| x).collect()).collect(); 49 | //! assert_eq!(output, expected); 50 | //! } 51 | //! 52 | //! let reusing_alloca: Vec = storage.into(); 53 | //! // keep using allocation of storage 54 | //! 55 | //! ``` 56 | //! 57 | //! ### Panics: 58 | //! 59 | //! As this iterator reuses the allocation for the yielded `Window`, no two instances of `Window` 60 | //! belonging to the same iterator may exist simultaneously. As noted above this is checked at runtime. 61 | //! 62 | //! ``` 63 | //! use sliding_windows::IterExt; 64 | //! use sliding_windows::Storage; 65 | //! 66 | //! let mut storage: Storage = Storage::new(3); 67 | //! let mut windowed_iter = (0..5).sliding_windows(&mut storage); 68 | //! 69 | //! // extra scope so that a doesn't live until the for loop 70 | //! { 71 | //! let a = windowed_iter.next(); 72 | //! //let b = windowed_iter.next(); => this would PANIC 73 | //! } 74 | //! 75 | //! // looping for example is fine though 76 | //! for _ in windowed_iter { 77 | //! // blah 78 | //! } 79 | //! ``` 80 | //! 81 | //! # Mutable Window: 82 | //! 83 | //! There is an implementation of an Iterator over `&'a mut T` for `Window<'a, T>`. It can be obtained 84 | //! by calling `iter_mut()`. For more information see [`Window<'a, T>`](struct.Window.html). 85 | //! 86 | //! However be aware that changes made to the items in the Window are persistent through calls to `next()`. 87 | 88 | #![cfg_attr(test, feature(test))] 89 | 90 | #[cfg(test)] 91 | extern crate test; 92 | 93 | #[cfg(test)] 94 | mod tests; 95 | 96 | #[cfg(test)] 97 | mod benches; 98 | 99 | mod sliding_windows; 100 | 101 | pub use sliding_windows::{ 102 | Storage, Adaptor, Window, WindowIter, WindowIterMut}; 103 | 104 | pub trait IterExt: Iterator { 105 | fn sliding_windows(self, storage: &mut Storage) 106 | -> Adaptor 107 | where Self: Sized 108 | { 109 | Adaptor::new(self, storage) 110 | } 111 | } 112 | 113 | impl IterExt for T where T: Iterator { } 114 | -------------------------------------------------------------------------------- /src/sliding_windows.rs: -------------------------------------------------------------------------------- 1 | use std::cell::{Cell, UnsafeCell}; 2 | use std::fmt; 3 | use std::marker::PhantomData; 4 | #[cfg(nightly)] 5 | use std::iterator::FusedIterator; 6 | 7 | /// This holds the backing allocation for the `Window` of an `Adaptor`. 8 | /// 9 | /// See [sliding_windows](index.html) for more information. 10 | pub struct Storage { 11 | window_size: usize, 12 | // this is the offset of the first element 13 | window_offset: Cell, 14 | /// acts as a refcount 15 | uniquely_owned: Cell, 16 | data: UnsafeCell>, 17 | } 18 | 19 | impl Storage { 20 | /// Create a new `Storage` with a given window size. 21 | /// This will allocate `window_size * sizeof::` bytes on the heap. 22 | /// 23 | /// See [sliding_windows](index.html) for more information. 24 | pub fn new(window_size: usize) -> Storage { 25 | Storage::from_vec(Vec::with_capacity(window_size), window_size) 26 | } 27 | 28 | /// Create a new `Storage` with a given window size from a given type implementing `Into`. 29 | /// The contents of the Vec will be removed. 30 | /// This will reuse the allocation of the Vec instead of allocating new memory. 31 | /// 32 | /// See [sliding_windows](index.html) for more information. 33 | pub fn from_vec>>(vec: S, window_size: usize) -> Storage { 34 | let mut vec = vec.into(); 35 | let missing: isize = window_size as isize - vec.capacity() as isize; 36 | if missing > 0 { 37 | vec.reserve_exact(missing as usize); 38 | } 39 | 40 | Storage { 41 | window_size: window_size, 42 | window_offset: Cell::new(0), 43 | uniquely_owned: Cell::new(true), 44 | data: UnsafeCell::new(vec) 45 | } 46 | } 47 | 48 | fn new_window<'a>(&'a self) -> Window<'a, T> { 49 | // assert that the last window went out of scope 50 | assert!(self.uniquely_owned.get(), "next() called before previous Window went out of scope"); 51 | let data = unsafe { &mut *self.data.get() }; 52 | let window_offset = self.window_offset.get(); 53 | 54 | self.uniquely_owned.set(false); 55 | 56 | Window { drop_flag: &self.uniquely_owned, data: &mut data[..], window_offset: window_offset } 57 | } 58 | 59 | // push value onto self, return true if window is full (for initialization) 60 | // this assumes that data.capacity >= self.window_size 61 | fn push(&self, elt: T) -> bool { 62 | assert!(self.uniquely_owned.get(), "next() called before previous Window went out of scope"); 63 | let data = unsafe { &mut *self.data.get() }; 64 | let window_offset = self.window_offset.get(); 65 | 66 | // if storage is not full simply push the element 67 | // this is only the case when filling storage initially 68 | if data.len() < self.window_size 69 | { 70 | data.push(elt); 71 | return data.len() == self.window_size; 72 | } 73 | 74 | debug_assert!(data.len() == self.window_size); 75 | 76 | // the storage is full, overwrite the last element 77 | let new_offset; 78 | if window_offset >= (self.window_size - 1) { 79 | new_offset = 0; 80 | } else { 81 | new_offset = window_offset + 1; 82 | } 83 | 84 | data[window_offset] = elt; 85 | self.window_offset.set(new_offset); 86 | true 87 | } 88 | 89 | // clear backing storage 90 | fn clear(&mut self) { 91 | assert!(self.uniquely_owned.get(), "next() called before previous Window went out of scope"); 92 | let data = unsafe { &mut *self.data.get() }; 93 | data.clear(); 94 | } 95 | } 96 | 97 | impl Into> for Storage { 98 | fn into(self) -> Vec { 99 | assert!(self.uniquely_owned.get(), "Storage dereferenced before previous Window went out of scope"); 100 | unsafe { 101 | self.data.into_inner() 102 | } 103 | } 104 | } 105 | 106 | /// This is the `Item` type of the `Adaptor` iterator. 107 | /// 108 | /// # Usage: 109 | /// 110 | /// Use [WindowIter](struct.WindowIter.html) or [WindowIterMut](struct.WindowIterMut.html) to access the elements of the Window. 111 | /// 112 | /// ``` 113 | /// use sliding_windows::IterExt; 114 | /// use sliding_windows::Storage; 115 | /// 116 | /// let mut storage: Storage = Storage::new(3); 117 | /// let mut windowed_iter = (0..5).sliding_windows(&mut storage); 118 | /// 119 | /// for mut window in windowed_iter { 120 | /// // extra scope, so that later mutable borrow is possible 121 | /// { 122 | /// for x in &window { 123 | /// // work with data immutably 124 | /// } 125 | /// } 126 | /// 127 | /// // mutable 128 | /// let mut iter_mut = window.iter_mut(); 129 | /// for x in iter_mut { 130 | /// // work with data mutably (affecting the next windows of course) 131 | /// } 132 | /// } 133 | /// ``` 134 | /// 135 | /// See [sliding_windows](index.html) for more information. 136 | pub struct Window<'a, T: 'a> { 137 | drop_flag: &'a Cell, 138 | // index of first element 139 | window_offset: usize, 140 | data: &'a mut [T], 141 | } 142 | 143 | impl<'a, T> Window<'a, T> 144 | { 145 | pub fn iter(&self) -> WindowIter { 146 | WindowIter { 147 | data: self.data, 148 | current_index: self.window_offset, 149 | iteration_num: 0 150 | } 151 | } 152 | 153 | pub fn iter_mut(&mut self) -> WindowIterMut { 154 | WindowIterMut { 155 | data: self.data.as_mut_ptr(), 156 | data_len: self.data.len(), 157 | current_index: self.window_offset, 158 | iteration_num: 0, 159 | _p: PhantomData 160 | } 161 | } 162 | } 163 | 164 | impl<'a, T> fmt::Debug for Window<'a, T> where T: fmt::Debug 165 | { 166 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 167 | f.write_str("Window")?; 168 | return f.debug_list().entries(self.into_iter()).finish(); 169 | } 170 | } 171 | 172 | impl<'a, T> Drop for Window<'a, T> { 173 | fn drop(&mut self) { 174 | // set flag to indicate this window was dropped 175 | self.drop_flag.set(true); 176 | } 177 | } 178 | 179 | impl<'a, 'b, T> PartialEq<&'b [T]> for Window<'a, T> where T: PartialEq 180 | { 181 | fn eq(&self, other: &&'b [T]) -> bool { 182 | if self.data.len() != other.len() { return false } 183 | for (i, x) in self.into_iter().enumerate() { 184 | if *x != other[i] { return false } 185 | } 186 | true 187 | } 188 | } 189 | 190 | impl<'a, T> IntoIterator for &'a Window<'a, T> 191 | { 192 | type Item = &'a T; 193 | type IntoIter = WindowIter<'a, T>; 194 | fn into_iter(self) -> Self::IntoIter { 195 | self.iter() 196 | } 197 | } 198 | 199 | pub struct WindowIter<'a, T: 'a> 200 | { 201 | data: &'a [T], 202 | current_index: usize, 203 | // number of next() calls made which returned Some(_) 204 | iteration_num: usize, 205 | } 206 | 207 | impl<'a, T> Iterator for WindowIter<'a, T> 208 | { 209 | type Item = &'a T; 210 | 211 | fn next(&mut self) -> Option { 212 | let current_element = &self.data[self.current_index]; 213 | 214 | if self.iteration_num >= self.data.len() { 215 | // the end was reached 216 | return None; 217 | } else if self.current_index >= (self.data.len() - 1) { 218 | // wrap around if the increment would create an invalid index 219 | self.current_index = 0; 220 | } else { 221 | self.current_index += 1; 222 | } 223 | 224 | self.iteration_num += 1; 225 | Some(current_element) 226 | } 227 | 228 | fn size_hint(&self) -> (usize, Option) { 229 | (self.data.len(), Some(self.data.len())) 230 | } 231 | } 232 | 233 | impl<'a, T> ExactSizeIterator for WindowIter<'a, T> {} 234 | #[cfg(nightly)] 235 | impl<'a, T> FusedIterator for WindowIter<'a, T> {} 236 | 237 | pub struct WindowIterMut<'a, T: 'a> 238 | { 239 | data: *mut T, 240 | data_len: usize, 241 | current_index: usize, 242 | // number of next() calls made which returned Some(_) 243 | iteration_num: usize, 244 | _p: PhantomData<&'a T>, 245 | } 246 | 247 | impl<'a, T> Iterator for WindowIterMut<'a, T> 248 | { 249 | type Item = &'a mut T; 250 | 251 | fn next(&mut self) -> Option { 252 | let current_element = unsafe { self.data.offset(self.current_index as isize).as_mut().unwrap() }; 253 | 254 | if self.iteration_num >= self.data_len { 255 | // the end was reached 256 | return None; 257 | } else if self.current_index >= (self.data_len - 1) { 258 | // wrap around if the increment would create an invalid index 259 | self.current_index = 0; 260 | } else { 261 | self.current_index += 1; 262 | } 263 | 264 | self.iteration_num += 1; 265 | Some(current_element) 266 | } 267 | 268 | fn size_hint(&self) -> (usize, Option) { 269 | (self.data_len, Some(self.data_len)) 270 | } 271 | } 272 | 273 | impl<'a, T> ExactSizeIterator for WindowIterMut<'a, T> {} 274 | #[cfg(nightly)] 275 | impl<'a, T> FusedIterator for WindowIterMut<'a, T> {} 276 | 277 | // TODO add other stuff like DoubleEndedIterator etc. 278 | 279 | /// See [sliding_windows](index.html) for more information. 280 | pub struct Adaptor<'a, I: Iterator> where ::Item: 'a { 281 | iter: I, 282 | done: bool, 283 | storage: &'a Storage, 284 | } 285 | 286 | impl<'a, I: Iterator> Adaptor<'a, I> { 287 | /// This creates a new Adaptor. Usually you should be using 288 | /// 289 | /// See [sliding_windows](index.html) for more information. 290 | pub fn new(iter: I, storage: &'a mut Storage) -> Adaptor<'a, I> { 291 | // in case the storage was reused 292 | storage.clear(); 293 | 294 | Adaptor { 295 | iter: iter, 296 | done: false, 297 | storage: storage, 298 | } 299 | } 300 | } 301 | 302 | impl<'a, I: Iterator> Iterator for Adaptor<'a, I> { 303 | type Item = Window<'a, I::Item>; 304 | 305 | fn next(&mut self) -> Option { 306 | if self.done || self.storage.window_size == 0 { 307 | return None; 308 | } 309 | self.done = true; 310 | 311 | for elt in &mut self.iter { 312 | self.done = false; 313 | if self.storage.push(elt) { 314 | break; 315 | } 316 | } 317 | 318 | if !self.done { 319 | // return new window 320 | Some(self.storage.new_window()) 321 | } else { 322 | None 323 | } 324 | } 325 | 326 | fn size_hint(&self) -> (usize, Option) { 327 | let size = self.storage.window_size; 328 | let (mut lower, mut upper): (usize, Option) = self.iter.size_hint(); 329 | 330 | if size == 0 { 331 | return (0, None); 332 | } 333 | 334 | lower = match lower { 335 | 0 => 0, 336 | x if x >= size => x - size + 1, 337 | _ => 1 338 | }; 339 | 340 | upper = upper.map(|upper| 341 | match upper { 342 | 0 => 0, 343 | x if x >= size => x - size + 1, 344 | _ => 1 345 | } 346 | ); 347 | 348 | (lower, upper) 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /src/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn sliding_windows_1() { 5 | fn test_window_correctness_with_storage(mut storage: Storage) { 6 | let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]]; 7 | 8 | { 9 | let windowed_iter = Adaptor::new(0..5, &mut storage); 10 | let output: Vec> = windowed_iter.map(|x| x.into_iter().map(|&x| x).collect()).collect(); 11 | assert_eq!(output, expected); 12 | } 13 | } 14 | 15 | let middle_alloc: Storage = Storage::new(3); 16 | let small_alloc: Storage = Storage::from_vec(vec![1u32; 1], 3); 17 | let exact_alloc: Storage = Storage::from_vec(vec![1u32; 3], 3); 18 | let big_alloc: Storage = Storage::from_vec(vec![1u32, 100], 3); 19 | 20 | test_window_correctness_with_storage(middle_alloc); 21 | test_window_correctness_with_storage(small_alloc); 22 | test_window_correctness_with_storage(exact_alloc); 23 | test_window_correctness_with_storage(big_alloc); 24 | } 25 | 26 | #[test] 27 | fn sliding_windows_2() { 28 | let it = 0..5; 29 | let mut storage: Storage = Storage::new(3); 30 | let windowed_iter = Adaptor::new(it, &mut storage); 31 | 32 | for mut window in windowed_iter { 33 | let mut iter_mut = window.iter_mut(); 34 | let element_0 = iter_mut.next().unwrap(); 35 | let mut element_1 = iter_mut.next().unwrap(); 36 | *element_1 = 0u32; 37 | assert_eq!(*element_0, 0); 38 | } 39 | } 40 | 41 | #[test] 42 | #[should_panic] 43 | fn sliding_windows_3() { 44 | let it = 0..5; 45 | let mut storage: Storage = Storage::new(3); 46 | let mut windowed_iter = Adaptor::new(it, &mut storage); 47 | 48 | let _a = windowed_iter.next(); 49 | let _b = windowed_iter.next(); 50 | } 51 | 52 | #[test] 53 | fn sliding_windows_4() { 54 | let mut storage1: Storage = Storage::new(3); 55 | let iter1 = Adaptor::new(0..5, &mut storage1); 56 | 57 | let mut storage2: Storage = Storage::new(5); 58 | let iter2 = Adaptor::new(0..5, &mut storage2); 59 | 60 | let mut storage3: Storage = Storage::new(6); 61 | let iter3 = Adaptor::new(0..5, &mut storage3); 62 | 63 | let mut storage4: Storage = Storage::new(6); 64 | let iter4 = Adaptor::new(42..42, &mut storage4); 65 | 66 | let mut storage5: Storage = Storage::new(6); 67 | let iter5 = Adaptor::new(42.., &mut storage5); 68 | 69 | assert_eq!(iter1.size_hint(), (3, Some(3))); 70 | assert_eq!(iter2.size_hint(), (1, Some(1))); 71 | assert_eq!(iter3.size_hint(), (1, Some(1))); 72 | assert_eq!(iter4.size_hint(), (0, Some(0))); 73 | assert_eq!(iter5.size_hint().1, None); 74 | } 75 | 76 | #[test] 77 | fn sliding_windows_5() { 78 | let range = 0..5; 79 | let mut storage: Storage = Storage::new(0); 80 | let mut iter = Adaptor::new(range, &mut storage); 81 | 82 | assert!(iter.next().is_none()); 83 | assert!(iter.next().is_none()); 84 | } 85 | 86 | #[test] 87 | fn sliding_windows_6() { 88 | let storage0: Storage = Storage::new(0); 89 | let storage0: Vec = storage0.into(); 90 | assert_eq!(storage0.capacity(), 0); 91 | 92 | let storage1: Storage = Storage::new(12); 93 | let storage1: Vec = storage1.into(); 94 | assert_eq!(storage1.capacity(), 12); 95 | 96 | let storage2: Storage = Storage::new(20); 97 | let storage2: Vec = storage2.into(); 98 | assert_eq!(storage2.capacity(), 20); 99 | } 100 | --------------------------------------------------------------------------------