1use aliasable::boxed::AliasableBox;
2use core::fmt;
3use maybe_dangling::MaybeDangling;
4
5use crate::{
6 Covar, FallibleLend, FallibleLender, FallibleLending, FusedFallibleLender, IntoFallibleLender,
7 Map, try_trait_v2::Try,
8};
9
10#[must_use = "lenders are lazy and do nothing unless consumed"]
16pub struct Flatten<'this, L: FallibleLender>
17where
18 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
19{
20 inner: FlattenCompat<'this, L>,
21}
22
23impl<L: FallibleLender> Flatten<'_, L>
24where
25 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
26{
27 #[inline]
28 pub(crate) fn new(lender: L) -> Self {
29 Self {
30 inner: FlattenCompat::new(lender),
31 }
32 }
33
34 #[inline(always)]
36 pub fn into_inner(self) -> L {
37 *AliasableBox::into_unique(self.inner.lender)
38 }
39}
40
41impl<L: FallibleLender + fmt::Debug> fmt::Debug for Flatten<'_, L>
46where
47 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
48 for<'all> <FallibleLend<'all, L> as IntoFallibleLender>::FallibleLender: fmt::Debug,
49{
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 f.debug_struct("Flatten")
52 .field("inner", &self.inner)
53 .finish()
54 }
55}
56
57impl<'lend, 'this, L: FallibleLender> FallibleLending<'lend> for Flatten<'this, L>
58where
59 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
60{
61 type Lend = FallibleLend<'lend, <FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender>;
62}
63
64impl<L: FallibleLender> FallibleLender for Flatten<'_, L>
65where
66 for<'all> FallibleLend<'all, L>: IntoFallibleLender<Error = L::Error>,
67{
68 type Error = L::Error;
69 crate::unsafe_assume_covariance_fallible!();
71
72 #[inline(always)]
73 fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
74 self.inner.next()
75 }
76
77 #[inline(always)]
78 fn size_hint(&self) -> (usize, Option<usize>) {
79 self.inner.size_hint()
80 }
81
82 #[inline(always)]
83 fn try_fold<B, F, R>(&mut self, init: B, f: F) -> Result<R, Self::Error>
84 where
85 Self: Sized,
86 F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
87 R: Try<Output = B>,
88 {
89 self.inner.try_fold(init, f)
90 }
91
92 #[inline(always)]
93 fn fold<B, F>(self, init: B, f: F) -> Result<B, Self::Error>
94 where
95 Self: Sized,
96 F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
97 {
98 self.inner.fold(init, f)
99 }
100
101 #[inline(always)]
102 fn count(self) -> Result<usize, Self::Error>
103 where
104 Self: Sized,
105 {
106 self.inner.count()
107 }
108}
109
110impl<L: FusedFallibleLender> FusedFallibleLender for Flatten<'_, L> where
111 for<'all> FallibleLend<'all, L>: IntoFallibleLender<Error = L::Error>
112{
113}
114
115#[must_use = "lenders are lazy and do nothing unless consumed"]
122pub struct FlatMap<'this, L: FallibleLender, F>
123where
124 Map<L, F>: FallibleLender,
125 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender,
126{
127 inner: FlattenCompat<'this, Map<L, F>>,
128}
129
130impl<L: FallibleLender, F> FlatMap<'_, L, F>
131where
132 Map<L, F>: FallibleLender,
133 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender,
134{
135 #[inline]
136 pub(crate) fn new(lender: L, f: Covar<F>) -> Self {
137 Self {
138 inner: FlattenCompat::new(Map::new_fallible(lender, f)),
139 }
140 }
141
142 #[inline(always)]
144 pub fn into_inner(self) -> L {
145 (*AliasableBox::into_unique(self.inner.lender)).into_inner()
146 }
147
148 #[inline(always)]
150 pub fn into_parts(self) -> (L, Covar<F>) {
151 (*AliasableBox::into_unique(self.inner.lender)).into_parts()
152 }
153}
154
155impl<L: FallibleLender + fmt::Debug, F> fmt::Debug for FlatMap<'_, L, F>
160where
161 Map<L, F>: FallibleLender,
162 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender,
163 for<'all> <FallibleLend<'all, Map<L, F>> as IntoFallibleLender>::FallibleLender: fmt::Debug,
164{
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.debug_struct("FlatMap")
167 .field("inner", &self.inner)
168 .finish()
169 }
170}
171
172impl<'lend, 'this, L: FallibleLender, F> FallibleLending<'lend> for FlatMap<'this, L, F>
173where
174 Map<L, F>: FallibleLender,
175 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender,
176{
177 type Lend =
178 FallibleLend<'lend, <FallibleLend<'this, Map<L, F>> as IntoFallibleLender>::FallibleLender>;
179}
180
181impl<L: FallibleLender, F> FallibleLender for FlatMap<'_, L, F>
182where
183 Map<L, F>: FallibleLender<Error = L::Error>,
184 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender<Error = L::Error>,
185{
186 type Error = L::Error;
187 crate::unsafe_assume_covariance_fallible!();
189
190 #[inline(always)]
191 fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
192 self.inner.next()
193 }
194
195 #[inline(always)]
196 fn size_hint(&self) -> (usize, Option<usize>) {
197 self.inner.size_hint()
198 }
199
200 #[inline(always)]
201 fn try_fold<B, G, R>(&mut self, init: B, f: G) -> Result<R, Self::Error>
202 where
203 Self: Sized,
204 G: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
205 R: Try<Output = B>,
206 {
207 self.inner.try_fold(init, f)
208 }
209
210 #[inline(always)]
211 fn fold<B, G>(self, init: B, f: G) -> Result<B, Self::Error>
212 where
213 Self: Sized,
214 G: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
215 {
216 self.inner.fold(init, f)
217 }
218
219 #[inline(always)]
220 fn count(self) -> Result<usize, Self::Error>
221 where
222 Self: Sized,
223 {
224 self.inner.count()
225 }
226}
227
228impl<L: FusedFallibleLender, F> FusedFallibleLender for FlatMap<'_, L, F>
229where
230 Map<L, F>: FallibleLender<Error = L::Error>,
231 for<'all> FallibleLend<'all, Map<L, F>>: IntoFallibleLender<Error = L::Error>,
232{
233}
234
235pub(crate) struct FlattenCompat<'this, L: FallibleLender>
238where
239 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
240{
241 inner: MaybeDangling<Option<<FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender>>,
248 lender: AliasableBox<L>,
249}
250
251impl<L: FallibleLender> FlattenCompat<'_, L>
252where
253 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
254{
255 #[inline]
256 pub(crate) fn new(lender: L) -> Self {
257 let _ = L::__check_covariance(crate::CovariantProof::new());
258 Self {
259 inner: MaybeDangling::new(None),
260 lender: AliasableBox::from_unique(alloc::boxed::Box::new(lender)),
261 }
262 }
263}
264
265impl<L: FallibleLender + fmt::Debug> fmt::Debug for FlattenCompat<'_, L>
270where
271 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
272 for<'all> <FallibleLend<'all, L> as IntoFallibleLender>::FallibleLender: fmt::Debug,
273{
274 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275 f.debug_struct("FlattenCompat")
276 .field("lender", &self.lender)
277 .field("inner", &self.inner)
278 .finish()
279 }
280}
281
282impl<'lend, 'this, L: FallibleLender> FallibleLending<'lend> for FlattenCompat<'this, L>
283where
284 for<'all> FallibleLend<'all, L>: IntoFallibleLender,
285{
286 type Lend = FallibleLend<'lend, <FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender>;
287}
288
289impl<'this, L: FallibleLender> FallibleLender for FlattenCompat<'this, L>
290where
291 for<'all> FallibleLend<'all, L>: IntoFallibleLender<Error = L::Error>,
292{
293 type Error = L::Error;
294 crate::unsafe_assume_covariance_fallible!();
296
297 #[inline]
298 fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
299 loop {
300 #[allow(clippy::deref_addrof)]
302 let reborrow = unsafe { &mut *(&raw mut *self.inner) };
303 if let Some(inner) = reborrow {
304 if let Some(x) = inner.next()? {
305 return Ok(Some(x));
306 }
307 }
308 *self.inner = self.lender.next()?.map(|l| unsafe {
312 core::mem::transmute::<
313 <FallibleLend<'_, L> as IntoFallibleLender>::FallibleLender,
314 <FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender,
315 >(l.into_fallible_lender())
316 });
317
318 if self.inner.is_none() {
319 return Ok(None);
320 }
321 }
322 }
323
324 #[inline]
325 fn size_hint(&self) -> (usize, Option<usize>) {
326 (
327 match &*self.inner {
328 Some(inner) => inner.size_hint().0,
329 None => 0,
330 },
331 None,
332 )
333 }
334
335 #[inline]
336 fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> Result<R, Self::Error>
337 where
338 Self: Sized,
339 F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
340 R: Try<Output = B>,
341 {
342 use core::ops::ControlFlow;
343 let mut acc = init;
344 if let Some(ref mut inner) = *self.inner {
345 match inner.try_fold(acc, &mut f)?.branch() {
346 ControlFlow::Continue(b) => acc = b,
347 ControlFlow::Break(r) => return Ok(R::from_residual(r)),
348 }
349 }
350 *self.inner = None;
351 loop {
352 let Some(l) = self.lender.next()? else { break };
353 *self.inner = Some(unsafe {
356 core::mem::transmute::<
357 <FallibleLend<'_, L> as IntoFallibleLender>::FallibleLender,
358 <FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender,
359 >(l.into_fallible_lender())
360 });
361 if let Some(ref mut inner) = *self.inner {
362 match inner.try_fold(acc, &mut f)?.branch() {
363 ControlFlow::Continue(b) => acc = b,
364 ControlFlow::Break(r) => return Ok(R::from_residual(r)),
365 }
366 }
367 *self.inner = None;
368 }
369 Ok(R::from_output(acc))
370 }
371
372 #[inline]
373 fn fold<B, F>(mut self, init: B, mut f: F) -> Result<B, Self::Error>
374 where
375 Self: Sized,
376 F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
377 {
378 let mut acc = init;
379 if let Some(inner) = self.inner.take() {
380 acc = inner.fold(acc, &mut f)?;
381 }
382 while let Some(l) = self.lender.next()? {
383 let sub = unsafe {
386 core::mem::transmute::<
387 <FallibleLend<'_, L> as IntoFallibleLender>::FallibleLender,
388 <FallibleLend<'this, L> as IntoFallibleLender>::FallibleLender,
389 >(l.into_fallible_lender())
390 };
391 acc = sub.fold(acc, &mut f)?;
392 }
393 Ok(acc)
394 }
395
396 #[inline]
397 fn count(self) -> Result<usize, Self::Error>
398 where
399 Self: Sized,
400 {
401 self.fold(0, |count, _| Ok(count + 1))
402 }
403}
404
405impl<L: FusedFallibleLender> FusedFallibleLender for FlattenCompat<'_, L> where
406 for<'all> FallibleLend<'all, L>: IntoFallibleLender<Error = L::Error>
407{
408}
409
410#[cfg(test)]
411mod test {
412 use core::convert::Infallible;
413
414 use super::*;
415 use crate::{IntoFallible, Lend, Lender, Lending};
416
417 struct Parent([i32; 4]);
418
419 impl<'lend> Lending<'lend> for Parent {
420 type Lend = Child<'lend>;
421 }
422
423 impl Lender for Parent {
424 crate::check_covariance!();
425 fn next(&mut self) -> Option<Lend<'_, Self>> {
426 Some(Child { array_ref: &self.0 })
427 }
428 }
429
430 struct Child<'a> {
431 array_ref: &'a [i32; 4],
432 }
433
434 impl<'a, 'lend> FallibleLending<'lend> for Child<'a> {
435 type Lend = &'lend [i32; 4];
436 }
437
438 impl<'a> FallibleLender for Child<'a> {
439 type Error = Infallible;
440 crate::check_covariance_fallible!();
441
442 fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
443 Ok(Some(self.array_ref))
444 }
445 }
446
447 #[test]
452 fn test_flatten() -> Result<(), Infallible> {
453 let lender = Parent([0, 1, 2, 3]);
454 let mut flatten = lender.into_fallible().flatten();
455 let _ = flatten.next();
456 moved_flatten(flatten)
457 }
458
459 fn moved_flatten(mut flatten: Flatten<IntoFallible<Parent>>) -> Result<(), Infallible> {
460 let next_array_ref = flatten.next()?.unwrap() as *const _;
461 let array_ref = &flatten.inner.lender.lender.0 as *const _;
462 assert_eq!(
463 next_array_ref, array_ref,
464 "Array references returned by the flattened FallibleLender should refer to the array in the parent FallibleLender"
465 );
466 Ok(())
467 }
468
469 #[test]
470 fn test_flat_map_empty() {
471 use crate::traits::IteratorExt;
472
473 let mut l = [1, 0, 2]
474 .into_iter()
475 .into_lender()
476 .into_fallible()
477 .flat_map(unsafe {
479 crate::Covar::__new(|n: i32| Ok((0..n).into_lender().into_fallible()))
480 });
481 assert_eq!(l.next(), Ok(Some(0)));
482 assert_eq!(l.next(), Ok(Some(0)));
483 assert_eq!(l.next(), Ok(Some(1)));
484 assert_eq!(l.next(), Ok(None));
485 assert_eq!(l.next(), Ok(None));
486 }
487}