diff --git a/src/string/mod.rs b/src/string/mod.rs index 2eef2cf0..2570a845 100644 --- a/src/string/mod.rs +++ b/src/string/mod.rs @@ -68,71 +68,6 @@ pub type String = StringInner>; /// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html). pub type StringView = StringInner>; -impl StringView { - /// Removes the specified range from the string in bulk, returning all - /// removed characters as an iterator. - /// - /// The returned iterator keeps a mutable borrow on the string to optimize - /// its implementation. - /// - /// # Panics - /// - /// Panics if the starting point or end point do not lie on a [`char`] - /// boundary, or if they're out of bounds. - /// - /// # Leaking - /// - /// If the returned iterator goes out of scope without being dropped (due to - /// [`core::mem::forget`], for example), the string may still contain a copy - /// of any drained characters, or may have lost characters arbitrarily, - /// including characters outside the range. - /// - /// # Examples - /// - /// ``` - /// use heapless::String; - /// - /// let mut s = String::<32>::try_from("α is alpha, β is beta").unwrap(); - /// let beta_offset = s.find('β').unwrap_or(s.len()); - /// - /// // Remove the range up until the β from the string - /// let t: String<32> = s.drain(..beta_offset).collect(); - /// assert_eq!(t, "α is alpha, "); - /// assert_eq!(s, "β is beta"); - /// - /// // A full range clears the string, like `clear()` does - /// s.drain(..); - /// assert_eq!(s, ""); - /// ``` - pub fn drain(&mut self, range: R) -> Drain<'_> - where - R: RangeBounds, - { - // Memory safety - // - // The `String` version of `Drain` does not have the memory safety issues - // of the `Vec` version. The data is just plain bytes. - // Because the range removal happens in `Drop`, if the `Drain` iterator is leaked, - // the removal will not happen. - let Range { start, end } = crate::slice::range(range, ..self.len()); - assert!(self.is_char_boundary(start)); - assert!(self.is_char_boundary(end)); - - // Take out two simultaneous borrows. The &mut String won't be accessed - // until iteration is over, in Drop. - let self_ptr = self as *mut _; - // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. - let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); - - Drain { - start, - end, - iter: chars_iter, - string: self_ptr, - } - } -} - impl String { /// Constructs a new, empty `String` with a fixed capacity of `N` bytes. /// @@ -275,7 +210,9 @@ impl String { pub fn into_bytes(self) -> Vec { self.vec } +} +impl + ?Sized> StringInner { /// Removes the specified range from the string in bulk, returning all /// removed characters as an iterator. /// @@ -315,11 +252,30 @@ impl String { where R: RangeBounds, { - self.as_mut_view().drain(range) - } -} + // Memory safety + // + // The `String` version of `Drain` does not have the memory safety issues + // of the `Vec` version. The data is just plain bytes. + // Because the range removal happens in `Drop`, if the `Drain` iterator is leaked, + // the removal will not happen. + let Range { start, end } = crate::slice::range(range, ..self.len()); + assert!(self.is_char_boundary(start)); + assert!(self.is_char_boundary(end)); + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self.as_mut_view() as *mut _; + // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks. + let chars_iter = unsafe { self.get_unchecked(start..end) }.chars(); + + Drain { + start, + end, + iter: chars_iter, + string: self_ptr, + } + } -impl + ?Sized> StringInner { /// Get a reference to the `String`, erasing the `N` const-generic. /// /// diff --git a/src/vec/mod.rs b/src/vec/mod.rs index 9ab08716..fb5e659d 100644 --- a/src/vec/mod.rs +++ b/src/vec/mod.rs @@ -479,48 +479,9 @@ impl Vec { } new } - - /// Removes the specified range from the vector in bulk, returning all - /// removed elements as an iterator. If the iterator is dropped before - /// being fully consumed, it drops the remaining removed elements. - /// - /// The returned iterator keeps a mutable borrow on the vector to optimize - /// its implementation. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - /// - /// # Leaking - /// - /// If the returned iterator goes out of scope without being dropped (due to - /// [`mem::forget`], for example), the vector may have lost and leaked - /// elements arbitrarily, including elements outside the range. - /// - /// # Examples - /// - /// ``` - /// use heapless::Vec; - /// - /// let mut v = Vec::<_, 8>::from_array([1, 2, 3]); - /// let u: Vec<_, 8> = v.drain(1..).collect(); - /// assert_eq!(v, &[1]); - /// assert_eq!(u, &[2, 3]); - /// - /// // A full range clears the vector, like `clear()` does. - /// v.drain(..); - /// assert_eq!(v, &[]); - /// ``` - pub fn drain(&mut self, range: R) -> Drain<'_, T> - where - R: RangeBounds, - { - self.as_mut_view().drain(range) - } } -impl VecView { +impl + ?Sized> VecInner { /// Removes the specified range from the vector in bulk, returning all /// removed elements as an iterator. If the iterator is dropped before /// being fully consumed, it drops the remaining removed elements. @@ -573,7 +534,7 @@ impl VecView { unsafe { // Set `self.vec` length's to `start`, to be safe in case `Drain` is leaked. self.set_len(start); - let vec = NonNull::from(self); + let vec = NonNull::from(self.as_mut_view()); let range_slice = slice::from_raw_parts(vec.as_ref().as_ptr().add(start), end - start); Drain { tail_start: end, @@ -583,9 +544,7 @@ impl VecView { } } } -} -impl + ?Sized> VecInner { /// Get a reference to the `Vec`, erasing the `N` const-generic. /// ///