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