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 
next(&mut self) -> Option<Self::Item>74     fn next(&mut self) -> Option<Self::Item> {
75         impl_next!(self, split_once_raw, |x| x)
76     }
77 }
78 
79 impl<P> Clone for Split<'_, P>
80 where
81     P: Pattern,
82 {
83     #[inline]
clone(&self) -> Self84     fn clone(&self) -> Self {
85         Self {
86             string: self.string,
87             pat: self.pat.clone(),
88         }
89     }
90 }
91 
92 impl<P> Debug for Split<'_, P>
93 where
94     P: Pattern,
95 {
96     #[inline]
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result97     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
98         f.debug_struct("Split")
99             .field("string", &self.string)
100             .field(
101                 "pat",
102                 &str::from_utf8(self.pat.__get()).expect("invalid pattern"),
103             )
104             .finish()
105     }
106 }
107 
108 impl<P> FusedIterator for Split<'_, P> where P: Pattern {}
109