Skip to content

Commit 3e7c9aa

Browse files
Genericise drain function over storage
1 parent 7759201 commit 3e7c9aa

File tree

2 files changed

+26
-111
lines changed

2 files changed

+26
-111
lines changed

src/string/mod.rs

Lines changed: 24 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -68,71 +68,6 @@ pub type String<const N: usize> = StringInner<OwnedVecStorage<u8, N>>;
6868
/// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
6969
pub type StringView = StringInner<ViewVecStorage<u8>>;
7070

71-
impl StringView {
72-
/// Removes the specified range from the string in bulk, returning all
73-
/// removed characters as an iterator.
74-
///
75-
/// The returned iterator keeps a mutable borrow on the string to optimize
76-
/// its implementation.
77-
///
78-
/// # Panics
79-
///
80-
/// Panics if the starting point or end point do not lie on a [`char`]
81-
/// boundary, or if they're out of bounds.
82-
///
83-
/// # Leaking
84-
///
85-
/// If the returned iterator goes out of scope without being dropped (due to
86-
/// [`core::mem::forget`], for example), the string may still contain a copy
87-
/// of any drained characters, or may have lost characters arbitrarily,
88-
/// including characters outside the range.
89-
///
90-
/// # Examples
91-
///
92-
/// ```
93-
/// use heapless::String;
94-
///
95-
/// let mut s = String::<32>::try_from("α is alpha, β is beta").unwrap();
96-
/// let beta_offset = s.find('β').unwrap_or(s.len());
97-
///
98-
/// // Remove the range up until the β from the string
99-
/// let t: String<32> = s.drain(..beta_offset).collect();
100-
/// assert_eq!(t, "α is alpha, ");
101-
/// assert_eq!(s, "β is beta");
102-
///
103-
/// // A full range clears the string, like `clear()` does
104-
/// s.drain(..);
105-
/// assert_eq!(s, "");
106-
/// ```
107-
pub fn drain<R>(&mut self, range: R) -> Drain<'_>
108-
where
109-
R: RangeBounds<usize>,
110-
{
111-
// Memory safety
112-
//
113-
// The `String` version of `Drain` does not have the memory safety issues
114-
// of the `Vec` version. The data is just plain bytes.
115-
// Because the range removal happens in `Drop`, if the `Drain` iterator is leaked,
116-
// the removal will not happen.
117-
let Range { start, end } = crate::slice::range(range, ..self.len());
118-
assert!(self.is_char_boundary(start));
119-
assert!(self.is_char_boundary(end));
120-
121-
// Take out two simultaneous borrows. The &mut String won't be accessed
122-
// until iteration is over, in Drop.
123-
let self_ptr = self as *mut _;
124-
// SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
125-
let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
126-
127-
Drain {
128-
start,
129-
end,
130-
iter: chars_iter,
131-
string: self_ptr,
132-
}
133-
}
134-
}
135-
13671
impl<const N: usize> String<N> {
13772
/// Constructs a new, empty `String` with a fixed capacity of `N` bytes.
13873
///
@@ -275,7 +210,9 @@ impl<const N: usize> String<N> {
275210
pub fn into_bytes(self) -> Vec<u8, N> {
276211
self.vec
277212
}
213+
}
278214

215+
impl<S: VecStorage<u8> + ?Sized> StringInner<S> {
279216
/// Removes the specified range from the string in bulk, returning all
280217
/// removed characters as an iterator.
281218
///
@@ -315,11 +252,30 @@ impl<const N: usize> String<N> {
315252
where
316253
R: RangeBounds<usize>,
317254
{
318-
self.as_mut_view().drain(range)
255+
// Memory safety
256+
//
257+
// The `String` version of `Drain` does not have the memory safety issues
258+
// of the `Vec` version. The data is just plain bytes.
259+
// Because the range removal happens in `Drop`, if the `Drain` iterator is leaked,
260+
// the removal will not happen.
261+
let Range { start, end } = crate::slice::range(range, ..self.len());
262+
assert!(self.is_char_boundary(start));
263+
assert!(self.is_char_boundary(end));
264+
265+
// Take out two simultaneous borrows. The &mut String won't be accessed
266+
// until iteration is over, in Drop.
267+
let self_ptr = self.as_mut_view() as *mut _;
268+
// SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
269+
let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
270+
271+
Drain {
272+
start,
273+
end,
274+
iter: chars_iter,
275+
string: self_ptr,
276+
}
319277
}
320-
}
321278

322-
impl<S: VecStorage<u8> + ?Sized> StringInner<S> {
323279
/// Get a reference to the `String`, erasing the `N` const-generic.
324280
///
325281
///

src/vec/mod.rs

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -479,48 +479,9 @@ impl<T, const N: usize> Vec<T, N> {
479479
}
480480
new
481481
}
482-
483-
/// Removes the specified range from the vector in bulk, returning all
484-
/// removed elements as an iterator. If the iterator is dropped before
485-
/// being fully consumed, it drops the remaining removed elements.
486-
///
487-
/// The returned iterator keeps a mutable borrow on the vector to optimize
488-
/// its implementation.
489-
///
490-
/// # Panics
491-
///
492-
/// Panics if the starting point is greater than the end point or if
493-
/// the end point is greater than the length of the vector.
494-
///
495-
/// # Leaking
496-
///
497-
/// If the returned iterator goes out of scope without being dropped (due to
498-
/// [`mem::forget`], for example), the vector may have lost and leaked
499-
/// elements arbitrarily, including elements outside the range.
500-
///
501-
/// # Examples
502-
///
503-
/// ```
504-
/// use heapless::Vec;
505-
///
506-
/// let mut v = Vec::<_, 8>::from_array([1, 2, 3]);
507-
/// let u: Vec<_, 8> = v.drain(1..).collect();
508-
/// assert_eq!(v, &[1]);
509-
/// assert_eq!(u, &[2, 3]);
510-
///
511-
/// // A full range clears the vector, like `clear()` does.
512-
/// v.drain(..);
513-
/// assert_eq!(v, &[]);
514-
/// ```
515-
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
516-
where
517-
R: RangeBounds<usize>,
518-
{
519-
self.as_mut_view().drain(range)
520-
}
521482
}
522483

523-
impl<T> VecView<T> {
484+
impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
524485
/// Removes the specified range from the vector in bulk, returning all
525486
/// removed elements as an iterator. If the iterator is dropped before
526487
/// being fully consumed, it drops the remaining removed elements.
@@ -573,7 +534,7 @@ impl<T> VecView<T> {
573534
unsafe {
574535
// Set `self.vec` length's to `start`, to be safe in case `Drain` is leaked.
575536
self.set_len(start);
576-
let vec = NonNull::from(self);
537+
let vec = NonNull::from(self.as_mut_view());
577538
let range_slice = slice::from_raw_parts(vec.as_ref().as_ptr().add(start), end - start);
578539
Drain {
579540
tail_start: end,
@@ -583,9 +544,7 @@ impl<T> VecView<T> {
583544
}
584545
}
585546
}
586-
}
587547

588-
impl<T, S: VecStorage<T> + ?Sized> VecInner<T, S> {
589548
/// Get a reference to the `Vec`, erasing the `N` const-generic.
590549
///
591550
///

0 commit comments

Comments
 (0)