1use crate::{ops::bounds_for, SmartString, SmartStringMode};
6use core::{
7 fmt::{Debug, Error, Formatter},
8 iter::FusedIterator,
9 ops::RangeBounds,
10 str::Chars,
11};
12
13pub 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}