• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::convert;
6 use std::fmt;
7 use std::fmt::Debug;
8 use std::fmt::Formatter;
9 use std::iter::FusedIterator;
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 {
32     #[track_caller]
new(string: &'a RawOsStr, pat: P) -> Self33     pub(super) fn new(string: &'a RawOsStr, pat: P) -> Self {
34         let pat = pat.__encode();
35         assert!(
36             !pat.__get().is_empty(),
37             "cannot split using an empty pattern",
38         );
39         Self {
40             string: Some(string),
41             pat,
42         }
43     }
44 }
45 
46 macro_rules! impl_next {
47     ( $self:ident , $split_method:ident , $swap_fn:expr ) => {{
48         $self
49             .string?
50             .$split_method(&$self.pat)
51             .map(|substrings| {
52                 let (substring, string) = $swap_fn(substrings);
53                 $self.string = Some(string);
54                 substring
55             })
56             .or_else(|| $self.string.take())
57     }};
58 }
59 
60 impl<P> Clone for Split<'_, P>
61 where
62     P: Pattern,
63 {
64     #[inline]
clone(&self) -> Self65     fn clone(&self) -> Self {
66         Self {
67             string: self.string,
68             pat: self.pat.clone(),
69         }
70     }
71 }
72 
73 impl<P> Debug for Split<'_, P>
74 where
75     P: Pattern,
76 {
77     #[inline]
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result78     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
79         f.debug_struct("Split")
80             .field("string", &self.string)
81             .field("pat", &self.pat)
82             .finish()
83     }
84 }
85 
86 impl<P> DoubleEndedIterator for Split<'_, P>
87 where
88     P: Pattern,
89 {
next_back(&mut self) -> Option<Self::Item>90     fn next_back(&mut self) -> Option<Self::Item> {
91         impl_next!(self, rsplit_once_raw, |(prefix, suffix)| (suffix, prefix))
92     }
93 }
94 
95 impl<P> FusedIterator for Split<'_, P> where P: Pattern {}
96 
97 impl<'a, P> Iterator for Split<'a, P>
98 where
99     P: Pattern,
100 {
101     type Item = &'a RawOsStr;
102 
103     #[inline]
last(mut self) -> Option<Self::Item>104     fn last(mut self) -> Option<Self::Item> {
105         self.next_back()
106     }
107 
next(&mut self) -> Option<Self::Item>108     fn next(&mut self) -> Option<Self::Item> {
109         impl_next!(self, split_once_raw, convert::identity)
110     }
111 }
112