1use core::{num::NonZeroUsize, ops::ControlFlow};
2
3use crate::{
4 try_trait_v2::{FromResidual, Try, internal::NeverShortCircuit},
5 *,
6};
7
8pub trait DoubleEndedLender: Lender {
10 fn next_back(&mut self) -> Option<Lend<'_, Self>>;
16
17 #[inline]
22 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
23 for i in 0..n {
24 if self.next_back().is_none() {
25 return Err(unsafe { NonZeroUsize::new_unchecked(n - i) });
27 }
28 }
29 Ok(())
30 }
31
32 #[inline]
36 fn nth_back(&mut self, n: usize) -> Option<Lend<'_, Self>> {
37 self.advance_back_by(n).ok()?;
38 self.next_back()
39 }
40
41 #[inline]
47 fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
48 where
49 F: FnMut(B, Lend<'_, Self>) -> R,
50 R: Try<Output = B>,
51 {
52 let mut accum = init;
53 while let Some(x) = self.next_back() {
54 accum = match f(accum, x).branch() {
55 ControlFlow::Break(x) => return FromResidual::from_residual(x),
56 ControlFlow::Continue(x) => x,
57 };
58 }
59 Try::from_output(accum)
60 }
61
62 #[inline]
67 fn rfold<B, F>(mut self, init: B, mut f: F) -> B
68 where
69 Self: Sized,
70 F: FnMut(B, Lend<'_, Self>) -> B,
71 {
72 self.try_rfold(init, |acc, x| NeverShortCircuit(f(acc, x)))
73 .0
74 }
75
76 #[inline]
81 fn rfind<P>(&mut self, mut predicate: P) -> Option<Lend<'_, Self>>
82 where
83 Self: Sized,
84 P: FnMut(&Lend<'_, Self>) -> bool,
85 {
86 while let Some(x) = self.next_back() {
87 if predicate(&x) {
88 return Some(unsafe { core::mem::transmute::<Lend<'_, Self>, Lend<'_, Self>>(x) });
90 }
91 }
92 None
93 }
94}
95
96impl<L: DoubleEndedLender> DoubleEndedLender for &mut L {
97 #[inline(always)]
98 fn next_back(&mut self) -> Option<Lend<'_, Self>> {
99 (**self).next_back()
100 }
101
102 #[inline(always)]
103 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
104 (**self).advance_back_by(n)
105 }
106
107 #[inline(always)]
108 fn nth_back(&mut self, n: usize) -> Option<Lend<'_, Self>> {
109 (**self).nth_back(n)
110 }
111}
112
113pub trait DoubleEndedFallibleLender: FallibleLender {
115 fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error>;
121
122 #[inline]
126 fn advance_back_by(&mut self, n: usize) -> Result<Result<(), NonZeroUsize>, Self::Error> {
127 for i in 0..n {
128 if self.next_back()?.is_none() {
129 return Ok(Err(unsafe { NonZeroUsize::new_unchecked(n - i) }));
131 }
132 }
133 Ok(Ok(()))
134 }
135
136 #[inline]
140 fn nth_back(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
141 if self.advance_back_by(n)?.is_err() {
142 return Ok(None);
143 }
144 self.next_back()
145 }
146
147 #[inline]
152 fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> Result<R, Self::Error>
153 where
154 F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
155 R: Try<Output = B>,
156 {
157 while let Some(v) = self.next_back()? {
158 match f(init, v)?.branch() {
159 ControlFlow::Break(residual) => return Ok(R::from_residual(residual)),
160 ControlFlow::Continue(output) => init = output,
161 }
162 }
163 Ok(R::from_output(init))
164 }
165
166 #[inline]
171 fn rfold<B, F>(mut self, init: B, mut f: F) -> Result<B, Self::Error>
172 where
173 Self: Sized,
174 F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
175 {
176 self.try_rfold(init, |acc, item| f(acc, item).map(NeverShortCircuit))
177 .map(|res| res.0)
178 }
179
180 #[inline]
185 fn rfind<P>(&mut self, mut predicate: P) -> Result<Option<FallibleLend<'_, Self>>, Self::Error>
186 where
187 Self: Sized,
188 P: FnMut(&FallibleLend<'_, Self>) -> Result<bool, Self::Error>,
189 {
190 while let Some(x) = self.next_back()? {
191 if predicate(&x)? {
192 return Ok(Some(unsafe {
194 core::mem::transmute::<FallibleLend<'_, Self>, FallibleLend<'_, Self>>(x)
195 }));
196 }
197 }
198 Ok(None)
199 }
200}
201
202impl<L: DoubleEndedFallibleLender> DoubleEndedFallibleLender for &mut L {
203 #[inline(always)]
204 fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
205 (**self).next_back()
206 }
207
208 #[inline(always)]
209 fn advance_back_by(&mut self, n: usize) -> Result<Result<(), NonZeroUsize>, Self::Error> {
210 (**self).advance_back_by(n)
211 }
212
213 #[inline(always)]
214 fn nth_back(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
215 (**self).nth_back(n)
216 }
217}