Skip to main content

lender/fallible_adapters/
chunky.rs

1use crate::{
2    Chunk, Chunky, FallibleLend, FallibleLender, FallibleLending, FusedFallibleLender,
3    try_trait_v2::Try,
4};
5use core::ops::ControlFlow;
6
7impl<'lend, L> FallibleLending<'lend> for Chunky<L>
8where
9    L: FallibleLender,
10{
11    type Lend = Chunk<'lend, L>;
12}
13
14impl<L> FallibleLender for Chunky<L>
15where
16    L: FallibleLender,
17{
18    type Error = L::Error;
19    // SAFETY: the lend is a Chunk wrapping L
20    crate::unsafe_assume_covariance_fallible!();
21
22    #[inline]
23    fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
24        if self.len > 0 {
25            self.len -= 1;
26            Ok(Some(self.lender.next_chunk(self.chunk_size)))
27        } else {
28            Ok(None)
29        }
30    }
31
32    #[inline]
33    fn nth(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
34        if n < self.len {
35            // Skip n chunks by advancing the inner lender
36            let skip = n
37                .checked_mul(self.chunk_size)
38                .expect("overflow in Chunky::nth");
39            self.len -= n;
40            if self.lender.advance_by(skip)?.is_err() {
41                unreachable!();
42            }
43            self.next()
44        } else {
45            // Exhaust
46            if self.len > 0 {
47                let skip = self
48                    .len
49                    .checked_mul(self.chunk_size)
50                    .expect("overflow in Chunky::nth");
51                let _ = self.lender.advance_by(skip)?;
52                self.len = 0;
53            }
54            Ok(None)
55        }
56    }
57
58    #[inline]
59    fn size_hint(&self) -> (usize, Option<usize>) {
60        (self.len, Some(self.len))
61    }
62
63    #[inline]
64    fn count(self) -> Result<usize, Self::Error> {
65        Ok(self.len)
66    }
67
68    #[inline]
69    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> Result<R, Self::Error>
70    where
71        Self: Sized,
72        F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
73        R: Try<Output = B>,
74    {
75        let mut acc = init;
76        let sz = self.chunk_size;
77        while self.len > 0 {
78            self.len -= 1;
79            acc = match f(acc, self.lender.next_chunk(sz))?.branch() {
80                ControlFlow::Break(x) => return Ok(R::from_residual(x)),
81                ControlFlow::Continue(x) => x,
82            };
83        }
84        Ok(R::from_output(acc))
85    }
86
87    #[inline]
88    fn fold<B, F>(mut self, init: B, mut f: F) -> Result<B, Self::Error>
89    where
90        Self: Sized,
91        F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
92    {
93        let mut accum = init;
94        let sz = self.chunk_size;
95        while self.len > 0 {
96            self.len -= 1;
97            accum = f(accum, self.lender.next_chunk(sz))?;
98        }
99        Ok(accum)
100    }
101}
102
103impl<L> FusedFallibleLender for Chunky<L> where L: FusedFallibleLender {}