1#![cfg_attr(not(any(test, feature = "std")), no_std)]
142
143#[cfg(doc)]
144use core::iter::{Product, Sum};
145use core::{
146 cell::RefCell,
147 iter::FusedIterator,
148 ops::{Add, Mul},
149};
150use num_traits::{One, Zero};
151
152pub trait IteratorILP: Iterator + Sized + TrustedLowerBound {
277 #[inline]
290 fn any_ilp<const STREAMS: usize>(self, mut predicate: impl FnMut(Self::Item) -> bool) -> bool {
291 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
292 self.find_map_ilp::<STREAMS, _>(|item| predicate(item).then_some(true))
293 .unwrap_or(false)
294 }
295
296 #[inline]
306 fn all_ilp<const STREAMS: usize>(self, mut predicate: impl FnMut(Self::Item) -> bool) -> bool {
307 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
308 self.find_map_ilp::<STREAMS, _>(|item| (!predicate(item)).then_some(false))
309 .unwrap_or(true)
310 }
311
312 #[inline]
322 fn find_ilp<const STREAMS: usize>(
323 self,
324 mut predicate: impl FnMut(&Self::Item) -> bool,
325 ) -> Option<Self::Item> {
326 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
327
328 let mut iter = self.map(|item| predicate(&item).then_some(item));
331
332 let stream_len = iter.size_hint().0 / STREAMS;
334 for _ in 0..stream_len {
335 let item_opts: [Option<Self::Item>; STREAMS] =
337 core::array::from_fn(|_| unsafe { iter.next().unwrap_unchecked() });
342
343 if let Some(item) = item_opts.into_iter().flatten().next() {
345 return Some(item);
346 }
347 }
348
349 iter.flatten().next()
351 }
352
353 #[inline]
363 fn find_map_ilp<const STREAMS: usize, Res>(
364 self,
365 f: impl FnMut(Self::Item) -> Option<Res>,
366 ) -> Option<Res> {
367 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
368 self.map(f)
369 .find_ilp::<STREAMS>(|res| res.is_some())
370 .flatten()
371 }
372
373 #[inline]
383 fn position_ilp<const STREAMS: usize>(
384 self,
385 mut predicate: impl FnMut(Self::Item) -> bool,
386 ) -> Option<usize> {
387 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
388 self.enumerate()
389 .find_map_ilp::<STREAMS, _>(|(idx, elem)| predicate(elem).then_some(idx))
390 }
391
392 #[inline]
402 fn rposition_ilp<const STREAMS: usize>(
403 self,
404 mut predicate: impl FnMut(Self::Item) -> bool,
405 ) -> Option<usize>
406 where
407 Self: DoubleEndedIterator + ExactSizeIterator,
408 {
409 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
410 self.enumerate()
411 .rev()
412 .find_map_ilp::<STREAMS, _>(|(idx, elem)| predicate(elem).then_some(idx))
413 }
414
415 #[inline]
435 fn fold_ilp<const STREAMS: usize, Acc>(
436 mut self,
437 mut neutral: impl FnMut() -> Acc,
438 mut accumulate: impl FnMut(Acc, Self::Item) -> Acc,
439 mut merge: impl FnMut(Acc, Acc) -> Acc,
440 ) -> Acc {
441 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
442
443 let mut accumulators: [Option<Acc>; STREAMS] = core::array::from_fn(|_| Some(neutral()));
445 let mut accumulate_opt = |accumulator: &mut Option<Acc>, item| {
446 if let Some(prev_acc) = accumulator.take() {
447 *accumulator = Some(accumulate(prev_acc, item));
448 }
449 };
450
451 let stream_len = self.size_hint().0 / STREAMS;
453 for _ in 0..stream_len {
454 for acc in &mut accumulators {
455 accumulate_opt(acc, unsafe { self.next().unwrap_unchecked() });
460 }
461 }
462
463 let mut stride = if STREAMS.is_power_of_two() {
465 STREAMS
466 } else {
467 STREAMS.next_power_of_two()
468 };
469 while stride > 1 {
470 stride /= 2;
471 for i in 0..stride.min(STREAMS - stride) {
472 accumulators[i] = Some(merge(
473 accumulators[i].take().unwrap(),
474 accumulators[i + stride].take().unwrap(),
475 ));
476 }
477 }
478 let ilp_result = accumulators[0].take().unwrap();
479
480 merge(ilp_result, self.fold(neutral(), accumulate))
483 }
484
485 #[inline]
498 fn reduce_ilp<const STREAMS: usize>(
499 self,
500 reduce: impl FnMut(Self::Item, Self::Item) -> Self::Item,
501 ) -> Option<Self::Item> {
502 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
503 let reduce = RefCell::new(reduce);
504 self.fold_ilp::<STREAMS, _>(
505 || None,
506 |acc_opt, item| {
507 Some(if let Some(acc) = acc_opt {
508 reduce.borrow_mut()(acc, item)
509 } else {
510 item
511 })
512 },
513 |acc_opt_1, acc_opt_2| match (acc_opt_1, acc_opt_2) {
514 (Some(a), Some(b)) => Some(reduce.borrow_mut()(a, b)),
515 (Some(a), _) | (_, Some(a)) => Some(a),
516 (None, None) => None,
517 },
518 )
519 }
520
521 #[inline(always)]
534 fn sum_ilp<const STREAMS: usize, S: Add<Self::Item, Output = S> + Add<S> + Zero>(self) -> S {
535 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
536 self.fold_ilp::<STREAMS, _>(|| S::zero(), |acc, it| acc + it, |acc1, acc2| acc1 + acc2)
537 }
538
539 #[inline]
550 fn product_ilp<const STREAMS: usize, P: Mul<Self::Item, Output = P> + Mul<P> + One>(self) -> P {
551 assert_ne!(STREAMS, 0, "Need at least one stream to make progress");
552 self.fold_ilp::<STREAMS, _>(|| P::one(), |acc, it| acc * it, |acc1, acc2| acc1 * acc2)
553 }
554}
555
556impl<I: Iterator + Sized + TrustedLowerBound> IteratorILP for I {}
557
558pub unsafe trait TrustedLowerBound: Iterator {}
577mod core_iters {
581 use crate::TrustedLowerBound;
582 use core::{
583 iter::{
584 Chain, Cloned, Copied, Cycle, Empty, Enumerate, Filter, FilterMap, FlatMap, Flatten,
585 FromFn, Fuse, Inspect, Map, MapWhile, Once, OnceWith, Peekable, Repeat, RepeatWith,
586 Rev, Scan, Skip, SkipWhile, StepBy, Successors, Take, TakeWhile, Zip,
587 },
588 ops::{Range, RangeFrom, RangeInclusive},
589 str::{CharIndices, Chars, EncodeUtf16, SplitAsciiWhitespace, SplitWhitespace},
590 };
591
592 unsafe impl<I> TrustedLowerBound for &mut I where I: TrustedLowerBound + ?Sized {}
593 unsafe impl<A, B> TrustedLowerBound for Chain<A, B>
594 where
595 A: TrustedLowerBound,
596 B: TrustedLowerBound<Item = <A as Iterator>::Item>,
597 {
598 }
599 unsafe impl TrustedLowerBound for CharIndices<'_> {}
600 unsafe impl TrustedLowerBound for Chars<'_> {}
601 unsafe impl<'a, I, T> TrustedLowerBound for Cloned<I>
602 where
603 I: TrustedLowerBound<Item = &'a T>,
604 T: 'a + Clone,
605 {
606 }
607 unsafe impl<'a, I, T> TrustedLowerBound for Copied<I>
608 where
609 I: TrustedLowerBound<Item = &'a T>,
610 T: 'a + Copy,
611 {
612 }
613 unsafe impl<I> TrustedLowerBound for Cycle<I> where I: TrustedLowerBound + Clone {}
614 unsafe impl<T> TrustedLowerBound for Empty<T> {}
615 unsafe impl TrustedLowerBound for EncodeUtf16<'_> {}
616 unsafe impl<I> TrustedLowerBound for Enumerate<I> where I: TrustedLowerBound {}
617 unsafe impl<I, P> TrustedLowerBound for Filter<I, P>
618 where
619 I: TrustedLowerBound,
620 P: FnMut(&<I as Iterator>::Item) -> bool,
621 {
622 }
623 unsafe impl<B, I, F> TrustedLowerBound for FilterMap<I, F>
624 where
625 F: FnMut(<I as Iterator>::Item) -> Option<B>,
626 I: TrustedLowerBound,
627 {
628 }
629 unsafe impl<I, U> TrustedLowerBound for Flatten<I>
630 where
631 I: TrustedLowerBound,
632 <I as Iterator>::Item: IntoIterator<IntoIter = U, Item = <U as Iterator>::Item>,
633 U: TrustedLowerBound,
634 {
635 }
636 unsafe impl<I, U, F> TrustedLowerBound for FlatMap<I, U, F>
637 where
638 I: TrustedLowerBound,
639 U: IntoIterator,
640 <U as IntoIterator>::IntoIter: TrustedLowerBound,
641 F: FnMut(<I as Iterator>::Item) -> U,
642 {
643 }
644 unsafe impl<T, F> TrustedLowerBound for FromFn<F> where F: FnMut() -> Option<T> {}
645 unsafe impl<I> TrustedLowerBound for Fuse<I> where I: TrustedLowerBound {}
646 unsafe impl<I, F> TrustedLowerBound for Inspect<I, F>
647 where
648 I: TrustedLowerBound,
649 F: FnMut(&<I as Iterator>::Item),
650 {
651 }
652 unsafe impl<B, I, F> TrustedLowerBound for Map<I, F>
653 where
654 F: FnMut(<I as Iterator>::Item) -> B,
655 I: TrustedLowerBound,
656 {
657 }
658 unsafe impl<B, I, F> TrustedLowerBound for MapWhile<I, F>
659 where
660 F: FnMut(<I as Iterator>::Item) -> Option<B>,
661 I: TrustedLowerBound,
662 {
663 }
664 unsafe impl<T> TrustedLowerBound for Once<T> {}
665 unsafe impl<A, F> TrustedLowerBound for OnceWith<F> where F: FnOnce() -> A {}
666 unsafe impl<I> TrustedLowerBound for Peekable<I> where I: TrustedLowerBound {}
667 unsafe impl TrustedLowerBound for Range<usize> {}
668 unsafe impl TrustedLowerBound for Range<isize> {}
669 unsafe impl TrustedLowerBound for Range<u8> {}
670 unsafe impl TrustedLowerBound for Range<i8> {}
671 unsafe impl TrustedLowerBound for Range<u16> {}
672 unsafe impl TrustedLowerBound for Range<i16> {}
673 unsafe impl TrustedLowerBound for Range<u32> {}
674 unsafe impl TrustedLowerBound for Range<i32> {}
675 unsafe impl TrustedLowerBound for Range<i64> {}
676 unsafe impl TrustedLowerBound for Range<u64> {}
677 unsafe impl TrustedLowerBound for RangeFrom<usize> {}
678 unsafe impl TrustedLowerBound for RangeFrom<isize> {}
679 unsafe impl TrustedLowerBound for RangeFrom<u8> {}
680 unsafe impl TrustedLowerBound for RangeFrom<i8> {}
681 unsafe impl TrustedLowerBound for RangeFrom<u16> {}
682 unsafe impl TrustedLowerBound for RangeFrom<i16> {}
683 unsafe impl TrustedLowerBound for RangeFrom<u32> {}
684 unsafe impl TrustedLowerBound for RangeFrom<i32> {}
685 unsafe impl TrustedLowerBound for RangeFrom<i64> {}
686 unsafe impl TrustedLowerBound for RangeFrom<u64> {}
687 unsafe impl TrustedLowerBound for RangeInclusive<usize> {}
688 unsafe impl TrustedLowerBound for RangeInclusive<isize> {}
689 unsafe impl TrustedLowerBound for RangeInclusive<u8> {}
690 unsafe impl TrustedLowerBound for RangeInclusive<i8> {}
691 unsafe impl TrustedLowerBound for RangeInclusive<u16> {}
692 unsafe impl TrustedLowerBound for RangeInclusive<i16> {}
693 unsafe impl TrustedLowerBound for RangeInclusive<u32> {}
694 unsafe impl TrustedLowerBound for RangeInclusive<i32> {}
695 unsafe impl TrustedLowerBound for RangeInclusive<i64> {}
696 unsafe impl TrustedLowerBound for RangeInclusive<u64> {}
697 unsafe impl<A: Clone> TrustedLowerBound for Repeat<A> {}
698 unsafe impl<A, F> TrustedLowerBound for RepeatWith<F> where F: FnMut() -> A {}
699 unsafe impl<I> TrustedLowerBound for Rev<I> where I: TrustedLowerBound + DoubleEndedIterator {}
700 unsafe impl<B, I, St, F> TrustedLowerBound for Scan<I, St, F>
701 where
702 F: FnMut(&mut St, <I as Iterator>::Item) -> Option<B>,
703 I: TrustedLowerBound,
704 {
705 }
706 unsafe impl<I> TrustedLowerBound for Skip<I> where I: TrustedLowerBound {}
707 unsafe impl<I, P> TrustedLowerBound for SkipWhile<I, P>
708 where
709 I: TrustedLowerBound,
710 P: FnMut(&<I as Iterator>::Item) -> bool,
711 {
712 }
713 unsafe impl TrustedLowerBound for SplitAsciiWhitespace<'_> {}
714 unsafe impl TrustedLowerBound for SplitWhitespace<'_> {}
715 unsafe impl<I> TrustedLowerBound for StepBy<I> where I: TrustedLowerBound {}
716 unsafe impl<T, F> TrustedLowerBound for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
717 unsafe impl<I> TrustedLowerBound for Take<I> where I: TrustedLowerBound {}
718 unsafe impl<I, P> TrustedLowerBound for TakeWhile<I, P>
719 where
720 I: TrustedLowerBound,
721 P: FnMut(&<I as Iterator>::Item) -> bool,
722 {
723 }
724 unsafe impl<A, B> TrustedLowerBound for Zip<A, B>
725 where
726 A: TrustedLowerBound,
727 B: TrustedLowerBound,
728 {
729 }
730 unsafe impl<T, const N: usize> TrustedLowerBound for core::array::IntoIter<T, N> {}
731 unsafe impl TrustedLowerBound for core::ascii::EscapeDefault {}
732 unsafe impl<I> TrustedLowerBound for core::char::DecodeUtf16<I> where
733 I: TrustedLowerBound<Item = u16>
734 {
735 }
736 unsafe impl TrustedLowerBound for core::char::EscapeDebug {}
737 unsafe impl TrustedLowerBound for core::char::EscapeDefault {}
738 unsafe impl TrustedLowerBound for core::char::EscapeUnicode {}
739 unsafe impl TrustedLowerBound for core::char::ToLowercase {}
740 unsafe impl TrustedLowerBound for core::char::ToUppercase {}
741 unsafe impl<A> TrustedLowerBound for core::option::Iter<'_, A> {}
742 unsafe impl<A> TrustedLowerBound for core::option::IterMut<'_, A> {}
743 unsafe impl<A> TrustedLowerBound for core::option::IntoIter<A> {}
744 unsafe impl<A> TrustedLowerBound for core::result::Iter<'_, A> {}
745 unsafe impl<A> TrustedLowerBound for core::result::IterMut<'_, A> {}
746 unsafe impl<A> TrustedLowerBound for core::result::IntoIter<A> {}
747 unsafe impl<T> TrustedLowerBound for core::slice::Chunks<'_, T> {}
748 unsafe impl<T> TrustedLowerBound for core::slice::ChunksExact<'_, T> {}
749 unsafe impl<T> TrustedLowerBound for core::slice::ChunksExactMut<'_, T> {}
750 unsafe impl<T> TrustedLowerBound for core::slice::ChunksMut<'_, T> {}
751 unsafe impl TrustedLowerBound for core::slice::EscapeAscii<'_> {}
752 unsafe impl<T> TrustedLowerBound for core::slice::Iter<'_, T> {}
753 unsafe impl<T> TrustedLowerBound for core::slice::IterMut<'_, T> {}
754 unsafe impl<T> TrustedLowerBound for core::slice::RChunks<'_, T> {}
755 unsafe impl<T> TrustedLowerBound for core::slice::RChunksExact<'_, T> {}
756 unsafe impl<T> TrustedLowerBound for core::slice::RChunksExactMut<'_, T> {}
757 unsafe impl<T> TrustedLowerBound for core::slice::RChunksMut<'_, T> {}
758 unsafe impl<T, P> TrustedLowerBound for core::slice::RSplit<'_, T, P> where P: FnMut(&T) -> bool {}
759 unsafe impl<T, P> TrustedLowerBound for core::slice::RSplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
760 unsafe impl<T, P> TrustedLowerBound for core::slice::RSplitN<'_, T, P> where P: FnMut(&T) -> bool {}
761 unsafe impl<T, P> TrustedLowerBound for core::slice::RSplitNMut<'_, T, P> where P: FnMut(&T) -> bool {}
762 unsafe impl<T, P> TrustedLowerBound for core::slice::Split<'_, T, P> where P: FnMut(&T) -> bool {}
763 unsafe impl<T, P> TrustedLowerBound for core::slice::SplitInclusive<'_, T, P> where
764 P: FnMut(&T) -> bool
765 {
766 }
767 unsafe impl<T, P> TrustedLowerBound for core::slice::SplitInclusiveMut<'_, T, P> where
768 P: FnMut(&T) -> bool
769 {
770 }
771 unsafe impl<T, P> TrustedLowerBound for core::slice::SplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
772 unsafe impl<T, P> TrustedLowerBound for core::slice::SplitN<'_, T, P> where P: FnMut(&T) -> bool {}
773 unsafe impl<T, P> TrustedLowerBound for core::slice::SplitNMut<'_, T, P> where P: FnMut(&T) -> bool {}
774 unsafe impl<T> TrustedLowerBound for core::slice::Windows<'_, T> {}
775 unsafe impl TrustedLowerBound for core::str::Bytes<'_> {}
776 unsafe impl TrustedLowerBound for core::str::EscapeDebug<'_> {}
777 unsafe impl TrustedLowerBound for core::str::EscapeDefault<'_> {}
778 unsafe impl TrustedLowerBound for core::str::EscapeUnicode<'_> {}
779 unsafe impl TrustedLowerBound for core::str::Lines<'_> {}
780
781 #[cfg(feature = "std")]
782 mod std {
783 use crate::TrustedLowerBound;
784 use core::hash::{BuildHasher, Hash};
785 use std::{
786 env::{Args, ArgsOs, SplitPaths, Vars, VarsOs},
787 fs::ReadDir,
788 io::{BufRead, Read},
789 path::{Ancestors, Components},
790 process::{CommandArgs, CommandEnvs},
791 sync::mpsc::TryIter,
792 vec::Splice,
793 };
794
795 unsafe impl TrustedLowerBound for Ancestors<'_> {}
796 unsafe impl TrustedLowerBound for Args {}
797 unsafe impl TrustedLowerBound for ArgsOs {}
798 unsafe impl<I> TrustedLowerBound for Box<I> where I: TrustedLowerBound {}
799 unsafe impl TrustedLowerBound for CommandArgs<'_> {}
800 unsafe impl TrustedLowerBound for CommandEnvs<'_> {}
801 unsafe impl TrustedLowerBound for Components<'_> {}
802 unsafe impl TrustedLowerBound for ReadDir {}
803 unsafe impl<I> TrustedLowerBound for Splice<'_, I> where I: TrustedLowerBound {}
804 unsafe impl TrustedLowerBound for SplitPaths<'_> {}
805 unsafe impl<T> TrustedLowerBound for TryIter<'_, T> {}
806 unsafe impl TrustedLowerBound for Vars {}
807 unsafe impl TrustedLowerBound for VarsOs {}
808 unsafe impl<T> TrustedLowerBound for std::collections::binary_heap::Drain<'_, T> {}
809 unsafe impl<T> TrustedLowerBound for std::collections::binary_heap::Iter<'_, T> {}
810 unsafe impl<T> TrustedLowerBound for std::collections::binary_heap::IntoIter<T> {}
811 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::IntoIter<K, V> {}
812 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::IntoKeys<K, V> {}
813 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::IntoValues<K, V> {}
814 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::Iter<'_, K, V> {}
815 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::IterMut<'_, K, V> {}
816 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::Keys<'_, K, V> {}
817 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::Range<'_, K, V> {}
818 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::RangeMut<'_, K, V> {}
819 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::Values<'_, K, V> {}
820 unsafe impl<K, V> TrustedLowerBound for std::collections::btree_map::ValuesMut<'_, K, V> {}
821 unsafe impl<T> TrustedLowerBound for std::collections::btree_set::IntoIter<T> {}
822 unsafe impl<T> TrustedLowerBound for std::collections::btree_set::Iter<'_, T> {}
823 unsafe impl<T> TrustedLowerBound for std::collections::btree_set::Range<'_, T> {}
824 unsafe impl<T: Ord> TrustedLowerBound for std::collections::btree_set::SymmetricDifference<'_, T> {}
825 unsafe impl<T: Ord> TrustedLowerBound for std::collections::btree_set::Union<'_, T> {}
826 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::Drain<'_, K, V> {}
827 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::IntoIter<K, V> {}
828 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::IntoKeys<K, V> {}
829 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::IntoValues<K, V> {}
830 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::Iter<'_, K, V> {}
831 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::IterMut<'_, K, V> {}
832 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::Keys<'_, K, V> {}
833 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::Values<'_, K, V> {}
834 unsafe impl<K, V> TrustedLowerBound for std::collections::hash_map::ValuesMut<'_, K, V> {}
835 unsafe impl<T, S> TrustedLowerBound for std::collections::hash_set::Difference<'_, T, S>
836 where
837 T: Eq + Hash,
838 S: BuildHasher,
839 {
840 }
841 unsafe impl<T, S> TrustedLowerBound for std::collections::hash_set::Intersection<'_, T, S>
842 where
843 T: Eq + Hash,
844 S: BuildHasher,
845 {
846 }
847 unsafe impl<T, S> TrustedLowerBound for std::collections::hash_set::SymmetricDifference<'_, T, S>
848 where
849 T: Eq + Hash,
850 S: BuildHasher,
851 {
852 }
853 unsafe impl<T, S> TrustedLowerBound for std::collections::hash_set::Union<'_, T, S>
854 where
855 T: Eq + Hash,
856 S: BuildHasher,
857 {
858 }
859 unsafe impl<K> TrustedLowerBound for std::collections::hash_set::Drain<'_, K> {}
860 unsafe impl<K> TrustedLowerBound for std::collections::hash_set::IntoIter<K> {}
861 unsafe impl<K> TrustedLowerBound for std::collections::hash_set::Iter<'_, K> {}
862 unsafe impl<T> TrustedLowerBound for std::collections::linked_list::IntoIter<T> {}
863 unsafe impl<T> TrustedLowerBound for std::collections::linked_list::Iter<'_, T> {}
864 unsafe impl<T> TrustedLowerBound for std::collections::linked_list::IterMut<'_, T> {}
865 unsafe impl<T> TrustedLowerBound for std::collections::vec_deque::Drain<'_, T> {}
866 unsafe impl<T> TrustedLowerBound for std::collections::vec_deque::IntoIter<T> {}
867 unsafe impl<T> TrustedLowerBound for std::collections::vec_deque::Iter<'_, T> {}
868 unsafe impl<T> TrustedLowerBound for std::collections::vec_deque::IterMut<'_, T> {}
869 unsafe impl<R: Read> TrustedLowerBound for std::io::Bytes<R> {}
870 unsafe impl<B: BufRead> TrustedLowerBound for std::io::Lines<B> {}
871 unsafe impl<B: BufRead> TrustedLowerBound for std::io::Split<B> {}
872 unsafe impl TrustedLowerBound for std::string::Drain<'_> {}
873 unsafe impl TrustedLowerBound for std::net::Incoming<'_> {}
874 unsafe impl TrustedLowerBound for std::path::Iter<'_> {}
875 unsafe impl<T> TrustedLowerBound for std::sync::mpsc::IntoIter<T> {}
876 unsafe impl<T> TrustedLowerBound for std::sync::mpsc::Iter<'_, T> {}
877 unsafe impl<T> TrustedLowerBound for std::vec::Drain<'_, T> {}
878 unsafe impl<T> TrustedLowerBound for std::vec::IntoIter<T> {}
879
880 #[cfg(target_os = "windows")]
881 mod windows {
882 use crate::TrustedLowerBound;
883 use std::os::windows::ffi::EncodeWide;
884
885 unsafe impl TrustedLowerBound for EncodeWide<'_> {}
886 }
887 }
888}
889
890#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
892pub struct AssertLowerBoundOk<I: Iterator>(I);
893impl<I: Iterator> AssertLowerBoundOk<I> {
895 #[inline]
902 pub unsafe fn new(inner: I) -> Self {
903 Self(inner)
904 }
905}
906impl<I: DoubleEndedIterator> DoubleEndedIterator for AssertLowerBoundOk<I> {
908 #[inline]
909 fn next_back(&mut self) -> Option<Self::Item> {
910 self.0.next_back()
911 }
912
913 #[inline]
914 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
915 self.0.nth_back(n)
916 }
917}
918impl<I: ExactSizeIterator> ExactSizeIterator for AssertLowerBoundOk<I> {
920 #[inline]
921 fn len(&self) -> usize {
922 self.0.len()
923 }
924}
925impl<I: FusedIterator> FusedIterator for AssertLowerBoundOk<I> {}
927impl<I: Iterator> Iterator for AssertLowerBoundOk<I> {
929 type Item = I::Item;
930
931 #[inline]
932 fn next(&mut self) -> Option<Self::Item> {
933 self.0.next()
934 }
935
936 #[inline]
937 fn size_hint(&self) -> (usize, Option<usize>) {
938 self.0.size_hint()
939 }
940
941 #[inline]
942 fn count(self) -> usize
943 where
944 I: Sized,
945 {
946 self.0.count()
947 }
948
949 #[inline]
950 fn last(self) -> Option<Self::Item>
951 where
952 I: Sized,
953 {
954 self.0.last()
955 }
956
957 #[inline]
958 fn nth(&mut self, n: usize) -> Option<Self::Item> {
959 self.0.nth(n)
960 }
961}
962unsafe impl<I: Iterator> TrustedLowerBound for AssertLowerBoundOk<I> {}
967
968#[cfg(test)]
969mod tests {
970 use super::*;
971 use proptest::prelude::*;
972 use static_assertions::assert_impl_all;
973
974 assert_impl_all!(
975 std::slice::Iter<'static, u32>: FusedIterator, TrustedLowerBound
976 );
977
978 proptest! {
979 #[test]
980 fn assert_lower_bound_basic(data: Vec<u8>) {
981 let raw = data.iter();
982 let iter = unsafe { AssertLowerBoundOk::new(raw.clone()) };
984 assert_eq!(iter.size_hint(), raw.size_hint());
985 assert_eq!(iter.len(), raw.len());
986 assert_eq!(iter.clone().count(), raw.clone().count());
987 assert_eq!(iter.clone().next(), raw.clone().next());
988 assert_eq!(iter.clone().next_back(), raw.clone().next_back());
989 assert_eq!(iter.clone().last(), raw.clone().last());
990 }
991
992 #[test]
993 fn assert_lower_bound_strided(data: Vec<u8>, stride: usize) {
994 let raw = data.iter();
995 let iter = unsafe { AssertLowerBoundOk::new(raw.clone()) };
997 assert_eq!(iter.clone().nth(stride), raw.clone().nth(stride));
998 assert_eq!(iter.clone().nth_back(stride), raw.clone().nth_back(stride));
999 }
1000
1001 #[test]
1002 fn any(dataset: Vec<u8>, needle: u8) {
1003 let predicate = |&item| item == needle;
1004 let expected = dataset.iter().any(predicate);
1005 prop_assert_eq!(dataset.iter().any_ilp::<1>(predicate), expected);
1006 prop_assert_eq!(dataset.iter().any_ilp::<2>(predicate), expected);
1007 prop_assert_eq!(dataset.iter().any_ilp::<3>(predicate), expected);
1008 prop_assert_eq!(dataset.iter().any_ilp::<4>(predicate), expected);
1009 prop_assert_eq!(dataset.iter().any_ilp::<5>(predicate), expected);
1010 prop_assert_eq!(dataset.iter().any_ilp::<6>(predicate), expected);
1011 }
1012
1013 #[test]
1014 fn all(dataset: Vec<u8>, needle: u8) {
1015 let predicate = |&item| item == needle;
1016 let expected = dataset.iter().all(predicate);
1017 prop_assert_eq!(dataset.iter().all_ilp::<1>(predicate), expected);
1018 prop_assert_eq!(dataset.iter().all_ilp::<2>(predicate), expected);
1019 prop_assert_eq!(dataset.iter().all_ilp::<3>(predicate), expected);
1020 prop_assert_eq!(dataset.iter().all_ilp::<4>(predicate), expected);
1021 prop_assert_eq!(dataset.iter().all_ilp::<5>(predicate), expected);
1022 prop_assert_eq!(dataset.iter().all_ilp::<6>(predicate), expected);
1023 }
1024
1025 #[test]
1026 fn find(dataset: Vec<u8>, needle: u8) {
1027 let predicate = |item: &&u8| **item == needle;
1028 let expected = dataset.iter().find(predicate);
1029 prop_assert_eq!(dataset.iter().find_ilp::<1>(predicate), expected);
1030 prop_assert_eq!(dataset.iter().find_ilp::<2>(predicate), expected);
1031 prop_assert_eq!(dataset.iter().find_ilp::<3>(predicate), expected);
1032 prop_assert_eq!(dataset.iter().find_ilp::<4>(predicate), expected);
1033 prop_assert_eq!(dataset.iter().find_ilp::<5>(predicate), expected);
1034 prop_assert_eq!(dataset.iter().find_ilp::<6>(predicate), expected);
1035 }
1036
1037 #[test]
1038 fn find_map(dataset: Vec<u8>, needle: u8) {
1039 let find_map = |item: &u8| (*item == needle).then_some(42);
1040 let expected = dataset.iter().find_map(find_map);
1041 prop_assert_eq!(dataset.iter().find_map_ilp::<1, _>(find_map), expected);
1042 prop_assert_eq!(dataset.iter().find_map_ilp::<2, _>(find_map), expected);
1043 prop_assert_eq!(dataset.iter().find_map_ilp::<3, _>(find_map), expected);
1044 prop_assert_eq!(dataset.iter().find_map_ilp::<4, _>(find_map), expected);
1045 prop_assert_eq!(dataset.iter().find_map_ilp::<5, _>(find_map), expected);
1046 prop_assert_eq!(dataset.iter().find_map_ilp::<6, _>(find_map), expected);
1047 }
1048
1049 #[test]
1050 fn position(dataset: Vec<u8>, needle: u8) {
1051 let predicate = |item: &u8| *item == needle;
1052 let expected = dataset.iter().position(predicate);
1053 prop_assert_eq!(dataset.iter().position_ilp::<1>(predicate), expected);
1054 prop_assert_eq!(dataset.iter().position_ilp::<2>(predicate), expected);
1055 prop_assert_eq!(dataset.iter().position_ilp::<3>(predicate), expected);
1056 prop_assert_eq!(dataset.iter().position_ilp::<4>(predicate), expected);
1057 prop_assert_eq!(dataset.iter().position_ilp::<5>(predicate), expected);
1058 prop_assert_eq!(dataset.iter().position_ilp::<6>(predicate), expected);
1059 }
1060
1061 #[test]
1062 fn rposition(dataset: Vec<u8>, needle: u8) {
1063 let predicate = |item: &u8| *item == needle;
1064 let expected = dataset.iter().rposition(predicate);
1065 prop_assert_eq!(dataset.iter().rposition_ilp::<1>(predicate), expected);
1066 prop_assert_eq!(dataset.iter().rposition_ilp::<2>(predicate), expected);
1067 prop_assert_eq!(dataset.iter().rposition_ilp::<3>(predicate), expected);
1068 prop_assert_eq!(dataset.iter().rposition_ilp::<4>(predicate), expected);
1069 prop_assert_eq!(dataset.iter().rposition_ilp::<5>(predicate), expected);
1070 prop_assert_eq!(dataset.iter().rposition_ilp::<6>(predicate), expected);
1071 }
1072
1073 #[test]
1074 fn fold(dataset: Vec<u8>) {
1075 let zero = || 0;
1076 let accumulate = |a, &b| a + b as u64;
1077 let merge = |a, b| a + b;
1078 let expected = dataset.iter().fold(zero(), accumulate);
1079 prop_assert_eq!(
1080 dataset.iter().fold_ilp::<1, _>(zero, accumulate, merge),
1081 expected
1082 );
1083 prop_assert_eq!(
1084 dataset.iter().fold_ilp::<2, _>(zero, accumulate, merge),
1085 expected
1086 );
1087 prop_assert_eq!(
1088 dataset.iter().fold_ilp::<3, _>(zero, accumulate, merge),
1089 expected
1090 );
1091 prop_assert_eq!(
1092 dataset.iter().fold_ilp::<4, _>(zero, accumulate, merge),
1093 expected
1094 );
1095 prop_assert_eq!(
1096 dataset.iter().fold_ilp::<5, _>(zero, accumulate, merge),
1097 expected
1098 );
1099 prop_assert_eq!(
1100 dataset.iter().fold_ilp::<6, _>(zero, accumulate, merge),
1101 expected
1102 );
1103 }
1104
1105 #[test]
1106 fn reduce(dataset: Vec<u64>) {
1107 let reduce = |a: u64, b| a.wrapping_add(b);
1108 let expected = dataset.iter().copied().reduce(reduce);
1109 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<1>(reduce), expected);
1110 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<2>(reduce), expected);
1111 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<3>(reduce), expected);
1112 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<4>(reduce), expected);
1113 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<5>(reduce), expected);
1114 prop_assert_eq!(dataset.iter().copied().reduce_ilp::<6>(reduce), expected);
1115 }
1116
1117 #[test]
1118 fn sum(dataset: Vec<u8>) {
1119 let dataset = dataset.into_iter().map(|i| i as u64).collect::<Vec<_>>();
1120 let expected = dataset.iter().copied().sum::<u64>();
1121 prop_assert_eq!(dataset.iter().copied().sum_ilp::<1, u64>(), expected);
1122 prop_assert_eq!(dataset.iter().copied().sum_ilp::<2, u64>(), expected);
1123 prop_assert_eq!(dataset.iter().copied().sum_ilp::<3, u64>(), expected);
1124 prop_assert_eq!(dataset.iter().copied().sum_ilp::<4, u64>(), expected);
1125 prop_assert_eq!(dataset.iter().copied().sum_ilp::<5, u64>(), expected);
1126 prop_assert_eq!(dataset.iter().copied().sum_ilp::<6, u64>(), expected);
1127 }
1128
1129 #[test]
1130 fn product(dataset: Vec<u8>) {
1131 let dataset = dataset
1132 .into_iter()
1133 .map(|i| (i as f64 / 256.0) + 0.5)
1134 .collect::<Vec<_>>();
1135 let expected = dataset.iter().copied().product::<f64>();
1136 let assert_close = |result: f64| {
1137 prop_assert!((result - expected).abs() < 1e-6 * expected.abs());
1138 Ok(())
1139 };
1140 assert_close(dataset.iter().copied().product_ilp::<1, f64>())?;
1141 assert_close(dataset.iter().copied().product_ilp::<2, f64>())?;
1142 assert_close(dataset.iter().copied().product_ilp::<3, f64>())?;
1143 assert_close(dataset.iter().copied().product_ilp::<4, f64>())?;
1144 assert_close(dataset.iter().copied().product_ilp::<5, f64>())?;
1145 assert_close(dataset.iter().copied().product_ilp::<6, f64>())?;
1146 }
1147 }
1148}