os_str_bytes/
iter.rs

1//! Iterators provided by this crate.
2
3#![cfg_attr(os_str_bytes_docs_rs, doc(cfg(feature = "raw_os_str")))]
4
5use std::fmt;
6use std::fmt::Debug;
7use std::fmt::Formatter;
8use std::iter::FusedIterator;
9use std::mem;
10
11use super::pattern::Encoded;
12use super::Pattern;
13use 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`].
20pub struct RawSplit<'a, P>
21where
22    P: Pattern,
23{
24    string: Option<&'a RawOsStr>,
25    pat: P::__Encoded,
26}
27
28impl<'a, P> RawSplit<'a, P>
29where
30    P: Pattern,
31{
32    #[track_caller]
33    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
46macro_rules! impl_next {
47    ( $self:ident , $split_method:ident , $swap:expr ) => {{
48        $self
49            .string?
50            .$split_method(&$self.pat)
51            .map(|(mut substring, mut string)| {
52                if $swap {
53                    mem::swap(&mut substring, &mut string);
54                }
55                $self.string = Some(string);
56                substring
57            })
58            .or_else(|| $self.string.take())
59    }};
60}
61
62impl<P> Clone for RawSplit<'_, P>
63where
64    P: Pattern,
65{
66    #[inline]
67    fn clone(&self) -> Self {
68        Self {
69            string: self.string,
70            pat: self.pat.clone(),
71        }
72    }
73}
74
75impl<P> Debug for RawSplit<'_, P>
76where
77    P: Pattern,
78{
79    #[inline]
80    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
81        f.debug_struct("RawSplit")
82            .field("string", &self.string)
83            .field("pat", &self.pat)
84            .finish()
85    }
86}
87
88impl<P> DoubleEndedIterator for RawSplit<'_, P>
89where
90    P: Pattern,
91{
92    fn next_back(&mut self) -> Option<Self::Item> {
93        impl_next!(self, rsplit_once_raw, true)
94    }
95}
96
97impl<P> FusedIterator for RawSplit<'_, P> where P: Pattern {}
98
99impl<'a, P> Iterator for RawSplit<'a, P>
100where
101    P: Pattern,
102{
103    type Item = &'a RawOsStr;
104
105    #[inline]
106    fn last(mut self) -> Option<Self::Item> {
107        self.next_back()
108    }
109
110    fn next(&mut self) -> Option<Self::Item> {
111        impl_next!(self, split_once_raw, false)
112    }
113}
114
115/// A temporary type alias providing backward compatibility.
116#[deprecated(since = "6.6.0", note = "use `RawSplit` instead")]
117pub type Split<'a, P> = RawSplit<'a, P>;