Skip to main content

bulks/adapters/
contained.rs

1use crate::Bulk;
2use crate::DoubleEndedBulk;
3use crate::IntoBulk;
4
5use array_trait::length;
6use array_trait::length::LengthValue;
7pub(crate) use private::IntoContained as IntoContained;
8#[allow(unused)]
9pub(crate) use private::IntoContainedIter as IntoContainedIter;
10pub(crate) use private::ContainedIntoIter as ContainedIntoIter;
11
12pub struct Contained<I>
13where
14    I: Iterator
15{
16    iter: I
17}
18
19impl<I> Iterator for Contained<I>
20where
21    I: Iterator
22{
23    type Item = I::Item;
24
25    fn next(&mut self) -> Option<Self::Item>
26    {
27        self.iter.next()
28    }
29}
30impl<I> ExactSizeIterator for Contained<I>
31where
32    I: Iterator
33{
34    fn len(&self) -> usize
35    {
36        Bulk::len(self)
37    }
38    fn is_empty(&self) -> bool
39    {
40        Bulk::is_empty(self)
41    }
42}
43impl<I> DoubleEndedIterator for Contained<I>
44where
45    I: DoubleEndedIterator
46{
47    fn next_back(&mut self) -> Option<Self::Item>
48    {
49        self.iter.next_back()
50    }
51}
52
53impl<I> Contained<I>
54where
55    I: Iterator
56{
57    /// # Safety
58    /// 
59    /// This creates a bulk that is possibly only invalid.
60    /// 
61    /// Always wrap this bulk in another bulk so that its length is limited.
62    pub(crate) const unsafe fn new(iter: I) -> Self
63    {
64        Self {
65            iter
66        }
67    }
68}
69
70impl<I> Bulk for Contained<I>
71where
72    I: Iterator
73{
74    default type MinLength = <I as private::InfiniteSpec>::Length;
75    default type MaxLength = <I as private::InfiniteSpec>::Length;
76
77    #[inline]
78    default fn len(&self) -> usize
79    {
80        self.iter.size_hint().1.unwrap_or(usize::MAX)
81    }
82
83    #[inline]
84    default fn is_empty(&self) -> bool
85    {
86        Bulk::len(self) == 0
87    }
88
89    fn first(mut self) -> Option<Self::Item>
90    where
91        Self: Sized
92    {
93        self.iter.next()
94    }
95    fn last(self) -> Option<Self::Item>
96    where
97        Self: Sized
98    {
99        self.iter.last()
100    }
101    fn nth<L>(mut self, n: L) -> Option<Self::Item>
102    where
103        Self: Sized,
104        L: LengthValue
105    {
106        self.iter.nth(length::value::len(n))
107    }
108    
109    #[inline]
110    default fn for_each<F>(self, _f: F)
111    where
112        Self: Sized,
113        F: FnMut(Self::Item)
114    {
115        panic!("Possibly infinite iterator.")
116    }
117    
118    #[inline]
119    default fn try_for_each<F, R>(self, _f: F) -> R
120    where
121        Self: Sized,
122        F: FnMut(Self::Item) -> R,
123        R: core::ops::Try<Output = ()>
124    {
125        panic!("Possibly infinite iterator.")
126    }
127}
128impl<I> Bulk for Contained<I>
129where
130    I: ExactSizeIterator
131{
132    type MinLength = <I as private::InfiniteSpec>::Length;
133    type MaxLength = <I as private::InfiniteSpec>::Length;
134
135    #[inline]
136    fn len(&self) -> usize
137    {
138        self.iter.len()
139    }
140
141    #[inline]
142    fn is_empty(&self) -> bool
143    {
144        self.iter.is_empty()
145    }
146    
147    #[inline]
148    fn for_each<F>(self, f: F)
149    where
150        Self: Sized,
151        F: FnMut(Self::Item)
152    {
153        self.iter.for_each(f);
154    }
155    
156    #[inline]
157    fn try_for_each<F, R>(mut self, f: F) -> R
158    where
159        Self: Sized,
160        F: FnMut(Self::Item) -> R,
161        R: core::ops::Try<Output = ()>
162    {
163        self.iter.try_for_each(f)
164    }
165}
166impl<I> DoubleEndedBulk for Contained<I>
167where
168    I: DoubleEndedIterator
169{
170    #[inline]
171    default fn rev_for_each<F>(self, _f: F)
172    where
173        Self: Sized,
174        F: FnMut(Self::Item)
175    {
176        panic!("Possibly infinite iterator.")
177    }
178    
179    #[inline]
180    default fn try_rev_for_each<F, R>(self, _f: F) -> R
181    where
182        Self: Sized,
183        F: FnMut(Self::Item) -> R,
184        R: core::ops::Try<Output = ()>
185    {
186        panic!("Possibly infinite iterator.")
187    }
188}
189impl<I> DoubleEndedBulk for Contained<I>
190where
191    I: DoubleEndedIterator + ExactSizeIterator
192{
193    #[inline]
194    fn rev_for_each<F>(self, f: F)
195    where
196        Self: Sized,
197        F: FnMut(Self::Item)
198    {
199        self.iter.rev().for_each(f);
200    }
201    
202    #[inline]
203    fn try_rev_for_each<F, R>(self, f: F) -> R
204    where
205        Self: Sized,
206        F: FnMut(Self::Item) -> R,
207        R: core::ops::Try<Output = ()>
208    {
209        self.iter.rev().try_for_each(f)
210    }
211}
212
213mod private
214{
215    use array_trait::{length::Length, same::Same};
216
217    use crate::{Contained, IntoBulk, util::InfiniteIterator};
218
219    pub trait InfiniteSpec
220    {
221        type Length: Length<Elem = ()> + ?Sized;
222    }
223    impl<I> InfiniteSpec for I
224    {
225        default type Length = [()];
226    }
227    impl<I> InfiniteSpec for I
228    where
229        I: InfiniteIterator
230    {
231        type Length = [(); usize::MAX];
232    }
233
234    /// # Safety
235    /// 
236    /// This creates an iterator that is possibly only invalid.
237    /// 
238    /// Always wrap this bulk in another bulk so that its length is limited.
239    #[allow(unused)]
240    pub unsafe trait IntoContainedIter: IntoIterator
241    {
242        type IntoContainedIter: ExactSizeIterator<Item = Self::Item>;
243
244        /// # Safety
245        /// 
246        /// This creates a bulk that is possibly only invalid.
247        /// 
248        /// Always wrap this bulk in another bulk so that its length is limited.
249        unsafe fn into_contained_iter(self) -> Self::IntoContainedIter;
250    }
251    unsafe impl<T> IntoContainedIter for T
252    where
253        T: IntoIterator
254    {
255        default type IntoContainedIter = Contained<T::IntoIter>;
256
257        default unsafe fn into_contained_iter(self) -> Self::IntoContainedIter
258        {
259            unsafe {
260                Contained::new(self.into_iter()).same().ok().unwrap()
261            }
262        }
263    }
264    unsafe impl<T> IntoContainedIter for T
265    where
266        T: IntoIterator<IntoIter: ExactSizeIterator>
267    {
268        type IntoContainedIter = T::IntoIter;
269
270        unsafe fn into_contained_iter(self) -> Self::IntoContainedIter
271        {
272            self.into_iter()
273        }
274    }
275
276    /// # Safety
277    /// 
278    /// This creates a bulk that is possibly only invalid.
279    /// 
280    /// Always wrap this bulk in another bulk so that its length is limited.
281    pub const unsafe trait IntoContained: IntoIterator
282    {
283        type IntoContained: ~const IntoBulk<Item = Self::Item, IntoIter: ExactSizeIterator<Item = Self::Item>>;
284
285        /// # Safety
286        /// 
287        /// This creates a bulk that is possibly only invalid.
288        /// 
289        /// Always wrap this bulk in another bulk so that its length is limited.
290        unsafe fn into_contained(self) -> Self::IntoContained;
291    }
292    unsafe impl<T> IntoContained for T
293    where
294        T: IntoIterator
295    {
296        default type IntoContained = Contained<T::IntoIter>;
297
298        default unsafe fn into_contained(self) -> Self::IntoContained
299        {
300            unsafe {
301                Contained::new(self.into_iter()).same().ok().unwrap()
302            }
303        }
304    }
305    unsafe impl<T> const IntoContained for T
306    where
307        T: ~const IntoBulk
308    {
309        type IntoContained = T;
310
311        unsafe fn into_contained(self) -> Self::IntoContained
312        {
313            self
314        }
315    }
316
317    /// # Safety
318    /// 
319    /// Assumes that the possibly infinite iterator is contained by another exact length iterator.
320    /// 
321    /// This is ok to use with adapters such as zip and take.
322    pub unsafe trait ContainedIntoIter: IntoIterator<IntoIter: ExactSizeIterator>
323    {
324        type ContainedIntoIter: Iterator<Item = Self::Item>;
325
326        unsafe fn contained_into_iter(self) -> Self::ContainedIntoIter;
327    }
328    unsafe impl<T> ContainedIntoIter for T
329    where
330        T: IntoIterator<IntoIter: ExactSizeIterator>
331    {
332        default type ContainedIntoIter = T::IntoIter;
333
334        default unsafe fn contained_into_iter(self) -> Self::ContainedIntoIter
335        {
336            self.into_iter().same().ok().unwrap()
337        }
338    }
339    unsafe impl<I> ContainedIntoIter for Contained<I>
340    where
341        I: Iterator
342    {
343        type ContainedIntoIter = I;
344
345        unsafe fn contained_into_iter(self) -> Self::ContainedIntoIter
346        {
347            self.iter
348        }
349    }
350
351    pub trait EitherIntoBulk<B>: IntoIterator
352    where
353        B: IntoIterator
354    {
355        type EitherIntoBulk: IntoIterator;
356    }
357    impl<T, B> EitherIntoBulk<B> for T
358    where
359        T: IntoIterator,
360        B: IntoIterator
361    {
362        default type EitherIntoBulk = T;
363    }
364    impl<T, B> EitherIntoBulk<B> for T
365    where
366        T: IntoIterator,
367        B: IntoBulk
368    {
369        type EitherIntoBulk = B;
370    }
371}
372
373#[rustc_on_unimplemented(
374    message = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
375    label = "neither `{Self}` nor `{B}` can be converted into bulks",
376)]
377pub trait EitherIntoBulk<B>: private::EitherIntoBulk<B, EitherIntoBulk: IntoBulk>
378where
379    B: IntoIterator
380{
381    
382}
383impl<T, B> EitherIntoBulk<B> for T
384where
385    T: private::EitherIntoBulk<B, EitherIntoBulk: IntoBulk>,
386    B: IntoIterator
387{
388    
389}
390
391#[rustc_on_unimplemented(
392    message = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
393    label = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
394)]
395pub const trait IntoContainedBy<B>: ~const IntoContained + EitherIntoBulk<B> + Sized
396where
397    B: IntoIterator
398{
399
400}
401impl<T, B> const IntoContainedBy<B> for T
402where
403    T: ~const IntoContained + EitherIntoBulk<B>,
404    B: IntoIterator
405{
406
407}