1 //! Iterators provided by this crate.
2 
3 #![cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "raw_os_str")))]
4 
5 use std::fmt;
6 use std::fmt::Debug;
7 use std::fmt::Formatter;
8 use std::iter::FusedIterator;
9 use std::str;
10 
11 use super::pattern::Encoded;
12 use super::Pattern;
13 use super::RawOsStr;
14 
15 // [memchr::memmem::FindIter] is not currently used, since this struct would
16 // become self-referential. Additionally, that iterator does not implement
17 // [DoubleEndedIterator], and its implementation would likely require
18 // significant changes to implement that trait.
19 /// The iterator returned by [`RawOsStr::split`].
20 pub struct Split<'a, P>
21 where
22     P: Pattern,
23 {
24     string: Option<&'a RawOsStr>,
25     pat: P::__Encoded,
26 }
27 
28 impl<'a, P> Split<'a, P>
29 where
30     P: Pattern,
31 {
new(string: &'a RawOsStr, pat: P) -> Self32     pub(super) fn new(string: &'a RawOsStr, pat: P) -> Self {
33         let pat = pat.__encode();
34         assert!(
35             !pat.__get().is_empty(),
36             "cannot split using an empty pattern",
37         );
38         Self {
39             string: Some(string),
40             pat,
41         }
42     }
43 }
44 
45 macro_rules! impl_next {
46     ( $self:ident , $split_method:ident , $swap_fn:expr ) => {{
47         $self
48             .string?
49             .$split_method(&$self.pat)
50             .map(|substrings| {
51                 let (substring, string) = $swap_fn(substrings);
52                 $self.string = Some(string);
53                 substring
54             })
55             .or_else(|| $self.string.take())
56     }};
57 }
58 
59 impl<P> DoubleEndedIterator for Split<'_, P>
60 where
61     P: Pattern,
62 {
next_back(&mut self) -> Option<Self::Item>63     fn next_back(&mut self) -> Option<Self::Item> {
64         impl_next!(self, rsplit_once_raw, |(prefix, suffix)| (suffix, prefix))
65     }
66 }
67 
68 impl<'a, P> Iterator for Split<'a, P>
69 where
70     P: Pattern,
71 {
72     type Item = &'a RawOsStr;
73 
74     #[inline]
last(mut self) -> Option<Self::Item>75     fn last(mut self) -> Option<Self::Item> {
76         self.next_back()
77     }
78 
next(&mut self) -> Option<Self::Item>79     fn next(&mut self) -> Option<Self::Item> {
80         impl_next!(self, split_once_raw, |x| x)
81     }
82 }
83 
84 impl<P> Clone for Split<'_, P>
85 where
86     P: Pattern,
87 {
88     #[inline]
clone(&self) -> Self89     fn clone(&self) -> Self {
90         Self {
91             string: self.string,
92             pat: self.pat.clone(),
93         }
94     }
95 }
96 
97 impl<P> Debug for Split<'_, P>
98 where
99     P: Pattern,
100 {
101     #[inline]
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result102     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
103         f.debug_struct("Split")
104             .field("string", &self.string)
105             .field(
106                 "pat",
107                 &str::from_utf8(self.pat.__get()).expect("invalid pattern"),
108             )
109             .finish()
110     }
111 }
112 
113 impl<P> FusedIterator for Split<'_, P> where P: Pattern {}
114