smartstring/
iter.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::{ops::bounds_for, SmartString, SmartStringMode};
6use core::{
7    fmt::{Debug, Error, Formatter},
8    iter::FusedIterator,
9    ops::RangeBounds,
10    str::Chars,
11};
12
13/// A draining iterator for a [`SmartString`].
14pub struct Drain<'a, Mode: SmartStringMode> {
15    string: *mut SmartString<Mode>,
16    start: usize,
17    end: usize,
18    iter: Chars<'a>,
19}
20
21impl<'a, Mode: SmartStringMode> Drain<'a, Mode> {
22    pub(crate) fn new<R>(string: &'a mut SmartString<Mode>, range: R) -> Self
23    where
24        R: RangeBounds<usize>,
25    {
26        let string_ptr: *mut _ = string;
27        let len = string.len();
28        let (start, end) = bounds_for(&range, len);
29        assert!(start <= end);
30        assert!(end <= len);
31        assert!(string.as_str().is_char_boundary(start));
32        assert!(string.as_str().is_char_boundary(end));
33
34        let iter = string.as_str()[start..end].chars();
35        Drain {
36            string: string_ptr,
37            start,
38            end,
39            iter,
40        }
41    }
42}
43
44impl<'a, Mode: SmartStringMode> Drop for Drain<'a, Mode> {
45    fn drop(&mut self) {
46        #[allow(unsafe_code)]
47        let string = unsafe { &mut *self.string };
48        debug_assert!(string.as_str().is_char_boundary(self.start));
49        debug_assert!(string.as_str().is_char_boundary(self.end));
50        string.replace_range(self.start..self.end, "");
51    }
52}
53
54impl<'a, Mode: SmartStringMode> Iterator for Drain<'a, Mode> {
55    type Item = char;
56
57    #[inline]
58    fn next(&mut self) -> Option<Self::Item> {
59        self.iter.next()
60    }
61
62    #[inline]
63    fn size_hint(&self) -> (usize, Option<usize>) {
64        self.iter.size_hint()
65    }
66}
67
68impl<'a, Mode: SmartStringMode> DoubleEndedIterator for Drain<'a, Mode> {
69    #[inline]
70    fn next_back(&mut self) -> Option<Self::Item> {
71        self.iter.next_back()
72    }
73}
74
75impl<'a, Mode: SmartStringMode> FusedIterator for Drain<'a, Mode> {}
76
77impl<'a, Mode: SmartStringMode> Debug for Drain<'a, Mode> {
78    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
79        f.pad("Drain { ... }")
80    }
81}