heapless/string/
drain.rs

1use core::{fmt, iter::FusedIterator, str::Chars};
2
3use crate::LenType;
4
5use super::StringView;
6
7/// A draining iterator for `String`.
8///
9/// This struct is created by the [`drain`] method on [`crate::String`]. See its
10/// documentation for more.
11///
12/// [`drain`]: crate::String::drain
13pub struct Drain<'a, LenT: LenType> {
14    /// Will be used as &'a mut String in the destructor
15    pub(super) string: *mut StringView<LenT>,
16    /// Stast of part to remove
17    pub(super) start: LenT,
18    /// End of part to remove
19    pub(super) end: LenT,
20    /// Current remaining range to remove
21    pub(super) iter: Chars<'a>,
22}
23
24impl<LenT: LenType> fmt::Debug for Drain<'_, LenT> {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        f.debug_tuple("Drain").field(&self.as_str()).finish()
27    }
28}
29
30unsafe impl<LenT: LenType> Sync for Drain<'_, LenT> {}
31unsafe impl<LenT: LenType> Send for Drain<'_, LenT> {}
32
33impl<LenT: LenType> Drop for Drain<'_, LenT> {
34    fn drop(&mut self) {
35        unsafe {
36            // Use `Vec::drain`. “Reaffirm” the bounds checks to avoid
37            // panic code being inserted again.
38            let self_vec = (*self.string).as_mut_vec();
39            let start = self.start.into_usize();
40            let end = self.end.into_usize();
41            if start <= end && end <= self_vec.len() {
42                self_vec.drain(start..end);
43            }
44        }
45    }
46}
47
48impl<LenT: LenType> Drain<'_, LenT> {
49    /// Returns the remaining (sub)string of this iterator as a slice.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use heapless::String;
55    ///
56    /// let mut s = String::<8>::try_from("abc").unwrap();
57    /// let mut drain = s.drain(..);
58    /// assert_eq!(drain.as_str(), "abc");
59    /// let _ = drain.next().unwrap();
60    /// assert_eq!(drain.as_str(), "bc");
61    /// ```
62    #[must_use]
63    pub fn as_str(&self) -> &str {
64        self.iter.as_str()
65    }
66}
67
68impl<LenT: LenType> AsRef<str> for Drain<'_, LenT> {
69    fn as_ref(&self) -> &str {
70        self.as_str()
71    }
72}
73
74impl<LenT: LenType> AsRef<[u8]> for Drain<'_, LenT> {
75    fn as_ref(&self) -> &[u8] {
76        self.as_str().as_bytes()
77    }
78}
79
80impl<LenT: LenType> Iterator for Drain<'_, LenT> {
81    type Item = char;
82
83    #[inline]
84    fn next(&mut self) -> Option<char> {
85        self.iter.next()
86    }
87
88    fn size_hint(&self) -> (usize, Option<usize>) {
89        self.iter.size_hint()
90    }
91
92    #[inline]
93    fn last(mut self) -> Option<char> {
94        self.next_back()
95    }
96}
97
98impl<LenT: LenType> DoubleEndedIterator for Drain<'_, LenT> {
99    #[inline]
100    fn next_back(&mut self) -> Option<char> {
101        self.iter.next_back()
102    }
103}
104
105impl<LenT: LenType> FusedIterator for Drain<'_, LenT> {}
106
107#[cfg(test)]
108mod tests {
109    use crate::String;
110
111    #[test]
112    fn drain_front() {
113        let mut s = String::<8>::try_from("abcd").unwrap();
114        let mut it = s.drain(..1);
115        assert_eq!(it.next(), Some('a'));
116        drop(it);
117        assert_eq!(s, "bcd");
118    }
119
120    #[test]
121    fn drain_middle() {
122        let mut s = String::<8>::try_from("abcd").unwrap();
123        let mut it = s.drain(1..3);
124        assert_eq!(it.next(), Some('b'));
125        assert_eq!(it.next(), Some('c'));
126        drop(it);
127        assert_eq!(s, "ad");
128    }
129
130    #[test]
131    fn drain_end() {
132        let mut s = String::<8>::try_from("abcd").unwrap();
133        let mut it = s.drain(3..);
134        assert_eq!(it.next(), Some('d'));
135        drop(it);
136        assert_eq!(s, "abc");
137    }
138}