From 2c6e67105e4967f8b37ebe9ed92880c6773eb29e Mon Sep 17 00:00:00 2001 From: The8472 Date: Mon, 12 Jul 2021 21:40:38 +0200 Subject: implement advance_(back_)_by on more iterators --- library/alloc/src/lib.rs | 1 + library/alloc/src/vec/into_iter.rs | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 2aed9d03bc0..ca41ce975e4 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -111,6 +111,7 @@ // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#![feature(iter_advance_by)] #![feature(iter_zip)] #![feature(lang_items)] #![feature(layout_for_ptr)] diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 4cb0a4b10bd..eae9ad076dc 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -161,6 +161,28 @@ impl Iterator for IntoIter { (exact, Some(exact)) } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let step_size = self.len().min(n); + if mem::size_of::() == 0 { + // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound + // effectively results in unsigned pointers representing positions 0..usize::MAX, + // which is valid for ZSTs. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, step_size as isize) as *mut T } + } else { + let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); + // SAFETY: the min() above ensures that step_size is in bounds + unsafe { + self.ptr = self.ptr.add(step_size); + ptr::drop_in_place(to_drop); + } + } + if step_size < n { + return Err(step_size); + } + Ok(()) + } + #[inline] fn count(self) -> usize { self.len() @@ -203,6 +225,29 @@ impl DoubleEndedIterator for IntoIter { Some(unsafe { ptr::read(self.end) }) } } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let step_size = self.len().min(n); + if mem::size_of::() == 0 { + // SAFETY: same as for advance_by() + self.end = unsafe { + arith_offset(self.end as *const i8, step_size.wrapping_neg() as isize) as *mut T + } + } else { + // SAFETY: same as for advance_by() + self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) }; + let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size); + // SAFETY: same as for advance_by() + unsafe { + ptr::drop_in_place(to_drop); + } + } + if step_size < n { + return Err(step_size); + } + Ok(()) + } } #[stable(feature = "rust1", since = "1.0.0")] -- cgit 1.4.1-3-g733a5