Skip to content

Commit 8380165

Browse files
authored
Merge pull request #363 from schultetwin1/add_remove_to_string
Implement `remove` for String
2 parents 11e4f1e + 088f03c commit 8380165

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/string.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,49 @@ impl<const N: usize> String<N> {
333333
Some(ch)
334334
}
335335

336+
/// Removes a [`char`] from this `String` at a byte position and returns it.
337+
///
338+
/// Note: Because this shifts over the remaining elements, it has a
339+
/// worst-case performance of *O*(*n*).
340+
///
341+
/// # Panics
342+
///
343+
/// Panics if `idx` is larger than or equal to the `String`'s length,
344+
/// or if it does not lie on a [`char`] boundary.
345+
///
346+
/// # Examples
347+
///
348+
/// Basic usage:
349+
///
350+
/// ```
351+
/// use heapless::String;
352+
///
353+
/// let mut s: String<8> = String::from("foo");
354+
///
355+
/// assert_eq!(s.remove(0), 'f');
356+
/// assert_eq!(s.remove(1), 'o');
357+
/// assert_eq!(s.remove(0), 'o');
358+
/// ```
359+
#[inline]
360+
pub fn remove(&mut self, index: usize) -> char {
361+
let ch = match self[index..].chars().next() {
362+
Some(ch) => ch,
363+
None => panic!("cannot remove a char from the end of a string"),
364+
};
365+
366+
let next = index + ch.len_utf8();
367+
let len = self.len();
368+
unsafe {
369+
core::ptr::copy(
370+
self.vec.as_ptr().add(next),
371+
self.vec.as_mut_ptr().add(index),
372+
len - next,
373+
);
374+
self.vec.set_len(len - (next - index));
375+
}
376+
ch
377+
}
378+
336379
/// Truncates this `String`, removing all contents.
337380
///
338381
/// While this means the `String` will have a length of zero, it does not
@@ -796,4 +839,27 @@ mod tests {
796839
assert_eq!(0, s.len());
797840
assert_eq!(8, s.capacity());
798841
}
842+
843+
#[test]
844+
fn remove() {
845+
let mut s: String<8> = String::from("foo");
846+
assert_eq!(s.remove(0), 'f');
847+
assert_eq!(s.as_str(), "oo");
848+
}
849+
850+
#[test]
851+
fn remove_uenc() {
852+
let mut s: String<8> = String::from("ĝėēƶ");
853+
assert_eq!(s.remove(2), 'ė');
854+
assert_eq!(s.remove(2), 'ē');
855+
assert_eq!(s.remove(2), 'ƶ');
856+
assert_eq!(s.as_str(), "ĝ");
857+
}
858+
859+
#[test]
860+
fn remove_uenc_combo_characters() {
861+
let mut s: String<8> = String::from("héy");
862+
assert_eq!(s.remove(2), '\u{0301}');
863+
assert_eq!(s.as_str(), "hey");
864+
}
799865
}

0 commit comments

Comments
 (0)