1#![doc(html_root_url = "https://docs.rs/fixed_heap")]
3#![crate_name = "fixed_heap"]
4#![warn(
5 missing_debug_implementations,
6 trivial_casts,
7 trivial_numeric_casts,
8 unused_lifetimes,
9 unused_import_braces,
10 clippy::shadow_unrelated
11)]
12#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
13#![cfg_attr(
14 all(nightly, feature = "unstable"),
15 feature(maybe_uninit_uninit_array, slice_swap_unchecked)
16)]
17#![cfg_attr(not(test), no_std)]
18
19use core::{
20 fmt::{Debug, Formatter, Result},
21 iter::FusedIterator,
22 mem::{self, ManuallyDrop, MaybeUninit},
23 slice::{Iter, IterMut},
24};
25
26pub struct FixedHeap<T, const N: usize> {
28 high: usize,
29 data: [MaybeUninit<T>; N],
30}
31
32impl<T, const N: usize> FixedHeap<T, N> {
33 pub fn new() -> Self {
45 Self {
46 high: 0,
47 #[cfg(all(nightly, feature = "unstable"))]
48 data: MaybeUninit::uninit_array(),
49 #[cfg(not(all(nightly, feature = "unstable")))]
50 data: unsafe { MaybeUninit::uninit().assume_init() },
51 }
52 }
53
54 pub fn copy_from_slice(&mut self, slice: &[T])
68 where
69 T: Copy,
70 {
71 assert!(slice.len() <= N);
72 self.high = slice.len();
73 self.as_slice_mut().copy_from_slice(slice);
74 }
75
76 #[inline(always)]
93 pub fn peek(&self) -> Option<&T> {
94 self.peek_at(0)
95 }
96
97 #[inline(always)]
115 pub fn peek_at(&self, index: usize) -> Option<&T> {
116 if index < self.high {
119 Some(unsafe { self.data.get_unchecked(index).assume_init_ref() })
120 } else {
121 None
122 }
123 }
124
125 pub fn add_last(&mut self, value: T) -> Option<T> {
148 if self.high == N {
149 Some(value)
151 } else {
152 unsafe {
156 *self.data.get_unchecked_mut(self.high) = MaybeUninit::new(value);
157 }
158 self.high += 1;
159 None
160 }
161 }
162
163 pub fn swap_remove(&mut self, index: usize) -> Option<T> {
191 if index < self.high {
192 self.high -= 1;
193
194 let removed_node = unsafe { self.data.get_unchecked(index).assume_init_read() };
198 unsafe {
200 *self.data.get_unchecked_mut(index) =
201 MaybeUninit::new(self.data.get_unchecked(self.high).assume_init_read());
202 }
203
204 Some(removed_node)
205 } else {
206 None
207 }
208 }
209
210 pub fn push<S, F>(&mut self, value: T, comparer: &F, state: &S) -> Option<T>
256 where
257 F: Fn(&T, &T, &S) -> bool,
258 {
259 let mut result = None;
260 let mut node_index = self.high;
261 if let Some(value) = self.add_last(value) {
262 if N == 0 {
264 return Some(value);
266 } else if self.high == N {
267 let mut smallest_index = N >> 1;
271 for index in N >> 1..N {
272 let node = unsafe { self.data.get_unchecked(index).assume_init_ref() };
273 let smallest =
274 unsafe { self.data.get_unchecked(smallest_index).assume_init_ref() };
275 if comparer(smallest, node, state) {
276 smallest_index = index;
277 }
278 }
279 let smallest = unsafe { self.data.get_unchecked(smallest_index).assume_init_ref() };
280 if comparer(&value, smallest, state) {
281 let replaced = mem::replace(
282 unsafe { self.data.get_unchecked_mut(smallest_index) },
283 MaybeUninit::new(value),
284 );
285 node_index = smallest_index;
286 result = Some(unsafe { replaced.assume_init() });
287 } else {
288 return Some(value);
289 }
290 }
291 }
292
293 while node_index != 0 {
294 let parent_index = (node_index - 1) >> 1;
295 let node = unsafe { self.data.get_unchecked(node_index).assume_init_ref() };
298 let parent = unsafe { self.data.get_unchecked(parent_index).assume_init_ref() };
299 if !comparer(node, parent, state) {
300 break;
301 }
302
303 #[cfg(all(nightly, feature = "unstable"))]
304 unsafe {
305 self.data.swap_unchecked(node_index, parent_index);
306 }
307 #[cfg(not(all(nightly, feature = "unstable")))]
308 self.data.swap(node_index, parent_index);
309
310 node_index = parent_index;
311 }
312
313 result
314 }
315
316 pub fn pop<S, F>(&mut self, comparer: &F, state: &S) -> Option<T>
360 where
361 F: Fn(&T, &T, &S) -> bool,
362 {
363 self.pop_at(0, comparer, state)
364 }
365
366 pub fn pop_at<S, F>(&mut self, index: usize, comparer: &F, state: &S) -> Option<T>
413 where
414 F: Fn(&T, &T, &S) -> bool,
415 {
416 if let Some(removed_node) = self.swap_remove(index) {
417 let mut node_index: usize = index;
418 loop {
419 let lchild_index = (node_index << 1) + 1;
420 let rchild_index = (node_index << 1) + 2;
421 let node = unsafe { self.data.get_unchecked(node_index).assume_init_ref() };
424 let swap = if rchild_index < self.high {
426 let lchild = unsafe { self.data.get_unchecked(lchild_index).assume_init_ref() };
427 let rchild = unsafe { self.data.get_unchecked(rchild_index).assume_init_ref() };
428 match comparer(lchild, rchild, state) {
429 true => (comparer(lchild, node, state), lchild_index),
430 false => (comparer(rchild, node, state), rchild_index),
431 }
432 } else if lchild_index < self.high {
433 let lchild = unsafe { self.data.get_unchecked(lchild_index).assume_init_ref() };
434 (comparer(lchild, node, state), lchild_index)
435 } else {
436 (false, 0)
437 };
438 if let (true, compared_index) = swap {
440 #[cfg(all(nightly, feature = "unstable"))]
441 unsafe {
442 self.data.swap_unchecked(node_index, compared_index);
443 }
444 #[cfg(not(all(nightly, feature = "unstable")))]
445 self.data.swap(node_index, compared_index);
446
447 node_index = compared_index;
448 } else {
449 break;
450 }
451 }
452
453 Some(removed_node)
454 } else {
455 None
456 }
457 }
458
459 #[inline(always)]
461 pub fn as_slice(&self) -> &[T] {
462 unsafe { core::slice::from_raw_parts(self.data.as_ptr() as *const T, self.high) }
463 }
464
465 #[inline(always)]
468 pub fn as_slice_mut(&mut self) -> &mut [T] {
469 unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr() as *mut T, self.high) }
470 }
471
472 #[inline(always)]
475 pub fn iter(&self) -> Iter<T> {
476 self.as_slice().iter()
477 }
478
479 #[inline(always)]
483 pub fn iter_mut(&mut self) -> IterMut<T> {
484 self.as_slice_mut().iter_mut()
485 }
486
487 #[inline(always)]
499 pub fn len(&self) -> usize {
500 self.high
501 }
502
503 #[inline(always)]
516 pub fn is_empty(&self) -> bool {
517 self.high == 0
518 }
519
520 #[inline(always)]
533 pub fn is_full(&self) -> bool {
534 self.high == N
535 }
536}
537
538unsafe impl<T: Sync, const N: usize> Sync for FixedHeap<T, N> {}
539unsafe impl<T: Send, const N: usize> Send for FixedHeap<T, N> {}
540
541impl<T, const N: usize> Drop for FixedHeap<T, N> {
542 #[inline(always)]
543 fn drop(&mut self) {
544 for i in 0..self.high {
545 unsafe { self.data.get_unchecked_mut(i).assume_init_drop() };
546 }
547 }
548}
549
550impl<T, const N: usize> Debug for FixedHeap<T, N>
551where
552 T: Debug,
553{
554 fn fmt(&self, f: &mut Formatter) -> Result {
555 f.debug_struct("FixedHeap")
556 .field("high", &self.high)
557 .field("data", &self.as_slice())
558 .finish()
559 }
560}
561
562impl<T, const N: usize> Default for FixedHeap<T, N> {
563 fn default() -> Self {
564 Self::new()
565 }
566}
567
568impl<'a, T: 'a, const N: usize> IntoIterator for &'a FixedHeap<T, N> {
569 type Item = &'a T;
570 type IntoIter = Iter<'a, T>;
571
572 fn into_iter(self) -> Self::IntoIter {
573 self.iter()
574 }
575}
576
577impl<'a, T: 'a, const N: usize> IntoIterator for &'a mut FixedHeap<T, N> {
578 type Item = &'a mut T;
579 type IntoIter = IterMut<'a, T>;
580
581 fn into_iter(self) -> Self::IntoIter {
582 self.iter_mut()
583 }
584}
585
586impl<T, const N: usize> IntoIterator for FixedHeap<T, N> {
587 type Item = T;
588 type IntoIter = IntoIter<T, N>;
589
590 fn into_iter(self) -> Self::IntoIter {
591 IntoIter {
592 next: 0,
593 heap: ManuallyDrop::new(self),
594 }
595 }
596}
597
598#[derive(Debug)]
600pub struct IntoIter<T, const N: usize> {
601 next: usize,
602 heap: ManuallyDrop<FixedHeap<T, N>>,
603}
604
605impl<T, const N: usize> Iterator for IntoIter<T, N> {
606 type Item = T;
607
608 fn next(&mut self) -> Option<T> {
609 if self.next < self.heap.high {
610 let index = self.next;
611 self.next += 1;
612 Some(unsafe { self.heap.data.get_unchecked(index).assume_init_read() })
616 } else {
617 None
618 }
619 }
620
621 fn size_hint(&self) -> (usize, Option<usize>) {
622 let size = self.heap.high - self.next;
623 (size, Some(size))
624 }
625}
626
627impl<T, const N: usize> Drop for IntoIter<T, N> {
628 #[inline(always)]
629 fn drop(&mut self) {
630 for i in self.next..self.heap.high {
631 unsafe { self.heap.data[i].assume_init_drop() };
634 }
635 }
636}
637
638impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
639impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
640
641#[cfg(test)]
642mod test {
643 use crate::*;
644 use core::cell::RefCell;
645 use rand::{rngs::ThreadRng, Rng};
646
647 #[test]
648 fn test_default() {
649 let heap: FixedHeap<i32, 4> = FixedHeap::default();
650 assert_eq!(&[0; 0], heap.as_slice());
651 }
652
653 #[test]
654 fn test_copy_from_slice() {
655 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
656 heap.copy_from_slice(&[0, 3]);
657 assert_eq!(&[0, 3], heap.as_slice());
658 heap.copy_from_slice(&[]);
659 assert_eq!(&[0; 0], heap.as_slice());
660 heap.copy_from_slice(&[1, 3, 6, 2]);
661 assert_eq!(&[1, 3, 6, 2], heap.as_slice());
662 }
663
664 #[test]
665 fn test_push_peek_pop() {
666 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
667 let comparer = |a: &i32, b: &i32, _: &()| a > b;
668 assert_eq!(None, heap.peek());
669 assert_eq!(heap.push(1, &comparer, &()), None);
670 assert_eq!(Some(&1), heap.peek());
671 assert_eq!(heap.push(3, &comparer, &()), None);
672 assert_eq!(Some(&3), heap.peek());
673 assert_eq!(heap.push(2, &comparer, &()), None);
674 assert_eq!(Some(&3), heap.peek());
675
676 assert_eq!(Some(3), heap.pop(&comparer, &()));
677 assert_eq!(Some(&2), heap.peek());
678 assert_eq!(Some(2), heap.pop(&comparer, &()));
679 assert_eq!(Some(&1), heap.peek());
680 assert_eq!(Some(1), heap.pop(&comparer, &()));
681 assert_eq!(None, heap.peek());
682 assert_eq!(None, heap.pop(&comparer, &()));
683 }
684
685 #[test]
686 fn test_add_last_swap_remove() {
687 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
688 assert_eq!(heap.add_last(1), None);
689 assert_eq!(heap.add_last(2), None);
690 assert_eq!(heap.add_last(4), None);
691 assert_eq!(heap.add_last(3), None);
692 assert_eq!(heap.add_last(5), Some(5));
693
694 assert_eq!(Some(1), heap.swap_remove(0));
695 assert_eq!(Some(3), heap.swap_remove(0));
696 assert_eq!(Some(4), heap.swap_remove(0));
697 assert_eq!(Some(2), heap.swap_remove(0));
698 assert_eq!(None, heap.swap_remove(0));
699 }
700
701 #[test]
702 fn test_push_full() {
703 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
704 let comparer = |a: &i32, b: &i32, _: &()| a > b;
705 assert_eq!(heap.push(1, &comparer, &()), None);
706 assert_eq!(heap.push(2, &comparer, &()), None);
707 assert_eq!(heap.push(4, &comparer, &()), None);
708 assert_eq!(heap.push(3, &comparer, &()), None);
709 assert_eq!(heap.push(5, &comparer, &()), Some(1));
710
711 assert_eq!(Some(5), heap.pop(&comparer, &()));
712 assert_eq!(Some(4), heap.pop(&comparer, &()));
713 assert_eq!(Some(3), heap.pop(&comparer, &()));
714 assert_eq!(Some(2), heap.pop(&comparer, &()));
715 assert_eq!(None, heap.pop(&comparer, &()));
716 }
717
718 #[test]
719 fn test_push_pop_equal() {
720 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
721 let comparer = |a: &i32, b: &i32, _: &()| a > b;
722 assert_eq!(heap.push(7, &comparer, &()), None);
723 assert_eq!(heap.push(7, &comparer, &()), None);
724 assert_eq!(heap.push(7, &comparer, &()), None);
725
726 assert_eq!(Some(7), heap.pop(&comparer, &()));
727 assert_eq!(Some(7), heap.pop(&comparer, &()));
728 assert_eq!(Some(7), heap.pop(&comparer, &()));
729 assert_eq!(None, heap.pop(&comparer, &()));
730 }
731
732 #[test]
733 fn test_keys() {
734 let mut heap: FixedHeap<usize, 4> = FixedHeap::new();
735 fn comparer(a: &usize, b: &usize, state: &[i32; 4]) -> bool {
736 state[*a] > state[*b]
737 }
738 let state = [1, 3, 1, 2];
739 assert_eq!(heap.push(0, &comparer, &state), None);
740 assert_eq!(heap.push(1, &comparer, &state), None);
741 assert_eq!(heap.push(3, &comparer, &state), None);
742
743 assert_eq!(Some(1), heap.pop(&comparer, &state));
744 assert_eq!(Some(3), heap.pop(&comparer, &state));
745 assert_eq!(Some(0), heap.pop(&comparer, &state));
746 assert_eq!(None, heap.pop(&comparer, &state));
747 }
748
749 #[test]
750 fn test_as_slice() {
751 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
752 let comparer = |a: &i32, b: &i32, _: &()| a > b;
753 assert_eq!(heap.push(7, &comparer, &()), None);
754 assert_eq!(heap.push(9, &comparer, &()), None);
755 assert_eq!(heap.push(2, &comparer, &()), None);
756 assert_eq!(heap.push(5, &comparer, &()), None);
757 assert_eq!(heap.push(8, &comparer, &()), None);
758 assert_eq!(heap.push(8, &comparer, &()), None);
759 assert_eq!(heap.push(3, &comparer, &()), None);
760
761 let slice = heap.as_slice();
762 assert_eq!(7, slice.len());
763 assert_eq!(9, slice[0]);
764 assert_eq!(8, slice[1]);
765 assert_eq!(8, slice[2]);
766 assert_eq!(5, slice[3]);
767 assert_eq!(7, slice[4]);
768 assert_eq!(2, slice[5]);
769 assert_eq!(3, slice[6]);
770 }
771
772 #[test]
773 fn test_debug() {
774 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
775 let comparer = |a: &i32, b: &i32, _: &()| a > b;
776 assert_eq!(heap.push(7, &comparer, &()), None);
777 assert_eq!(heap.push(9, &comparer, &()), None);
778 assert_eq!(heap.push(2, &comparer, &()), None);
779 assert_eq!(heap.push(5, &comparer, &()), None);
780 assert_eq!(heap.push(8, &comparer, &()), None);
781 assert_eq!(heap.push(8, &comparer, &()), None);
782 assert_eq!(heap.push(3, &comparer, &()), None);
783 assert_eq!(
784 format!("{:?}", heap.into_iter()),
785 "IntoIter { next: 0, heap: ManuallyDrop { value: FixedHeap { high: 7, data: [9, 8, 8, 5, 7, 2, 3] } } }"
786 );
787 }
788
789 #[test]
790 fn test_iter() {
791 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
792 assert_eq!(None, heap.iter().next());
793 heap.copy_from_slice(&[2, 3, 6]);
794 let mut iter = heap.iter();
795 assert_eq!(Some(&2), iter.next());
796 assert_eq!(Some(&3), iter.next());
797 assert_eq!(Some(&6), iter.next());
798 assert_eq!(None, iter.next());
799 }
800
801 #[test]
802 fn test_iter_mut() {
803 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
804 assert_eq!(None, heap.iter_mut().next());
805 heap.copy_from_slice(&[2, 3, 6]);
806 let mut iter = heap.iter_mut();
807 *iter.next().unwrap() = 5;
808 *iter.next().unwrap() = 4;
809 *iter.next().unwrap() = 2;
810 assert_eq!(&[5, 4, 2], heap.as_slice());
811 }
812
813 #[test]
814 fn test_into_iter() {
815 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
816 heap.copy_from_slice(&[2, 3, 6]);
817 let mut iter = heap.into_iter();
818 assert_eq!((3, Some(3)), iter.size_hint());
819 assert_eq!(Some(2), iter.next());
820 assert_eq!(Some(3), iter.next());
821 assert_eq!(Some(6), iter.next());
822 assert_eq!(None, iter.next());
823 }
824
825 #[test]
826 fn test_into_iter_ref() {
827 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
828 assert_eq!(None, (&heap).into_iter().next());
829 heap.copy_from_slice(&[2, 3, 6]);
830 let mut iter = (&heap).into_iter();
831 assert_eq!(Some(&2), iter.next());
832 assert_eq!(Some(&3), iter.next());
833 assert_eq!(Some(&6), iter.next());
834 assert_eq!(None, iter.next());
835 }
836
837 #[test]
838 fn test_into_iter_mut() {
839 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
840 assert_eq!(None, (&mut heap).into_iter().next());
841 heap.copy_from_slice(&[2, 3, 6]);
842 let mut iter = (&mut heap).into_iter();
843 *iter.next().unwrap() = 5;
844 *iter.next().unwrap() = 4;
845 *iter.next().unwrap() = 2;
846 assert_eq!(&[5, 4, 2], heap.as_slice());
847 }
848
849 #[test]
850 fn test_len() {
851 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
852 assert_eq!(0, heap.len());
853 heap.copy_from_slice(&[2, 3, 6]);
854 assert_eq!(3, heap.len());
855 }
856
857 #[test]
858 fn test_is_empty() {
859 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
860 assert!(heap.is_empty());
861 heap.copy_from_slice(&[2, 3, 6]);
862 assert!(!heap.is_empty());
863 }
864
865 #[test]
866 fn test_is_full() {
867 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
868 assert!(!heap.is_full());
869 heap.copy_from_slice(&[2, 3, 6]);
870 assert!(!heap.is_full());
871 heap.copy_from_slice(&[4, 1, 5, 3]);
872 assert!(heap.is_full());
873 }
874
875 #[test]
876 fn test_drop() {
877 let drops = RefCell::new(0usize);
878 {
879 let comparer = |_: &_, _: &_, _: &()| false;
880 let mut list: FixedHeap<DropCounted, 16> = FixedHeap::new();
881 for _ in 0..11 {
882 list.push(DropCounted(&drops), &comparer, &());
883 }
884 assert_eq!(*drops.borrow(), 0);
885
886 for _ in 0..4 {
888 list.pop(&comparer, &());
889 }
890 assert_eq!(*drops.borrow(), 4);
891
892 let mut iter = list.into_iter();
894 assert_eq!(*drops.borrow(), 4);
895
896 iter.next();
898 assert_eq!(*drops.borrow(), 5);
899
900 }
902 assert_eq!(*drops.borrow(), 11);
903 }
904
905 struct DropCounted<'a>(&'a RefCell<usize>);
906
907 impl<'a> Drop for DropCounted<'a> {
908 fn drop(&mut self) {
909 *self.0.borrow_mut() += 1;
910 }
911 }
912
913 #[test]
914 fn test_fuzz_gt_partial() {
915 let gt = |a: &i8, b: &i8, _: &()| a > b;
916 fuzz::<_, 8, 7>(10, >);
917 fuzz::<_, 9, 7>(10, >);
918 fuzz::<_, 10, 7>(10, >);
919 fuzz::<_, 11, 7>(10, >);
920 fuzz::<_, 12, 7>(10, >);
921 fuzz::<_, 13, 7>(10, >);
922 fuzz::<_, 14, 7>(10, >);
923 fuzz::<_, 15, 7>(10, >);
924 fuzz::<_, 16, 7>(10, >);
925 }
926
927 #[test]
928 fn test_fuzz_gt_full() {
929 let gt = |a: &i8, b: &i8, _: &()| a > b;
930 fuzz::<_, 0, 4>(10, >);
931 fuzz::<_, 1, 4>(10, >);
932 fuzz::<_, 2, 4>(10, >);
933 fuzz::<_, 3, 4>(10, >);
934 fuzz::<_, 8, 16>(10, >);
935 fuzz::<_, 9, 16>(10, >);
936 fuzz::<_, 10, 16>(10, >);
937 fuzz::<_, 11, 16>(10, >);
938 fuzz::<_, 12, 16>(10, >);
939 fuzz::<_, 13, 16>(10, >);
940 fuzz::<_, 14, 16>(10, >);
941 fuzz::<_, 15, 16>(10, >);
942 }
943
944 #[test]
945 fn test_fuzz_ge_partial() {
946 let ge = |a: &i8, b: &i8, _: &()| a >= b;
947 fuzz::<_, 8, 7>(10, &ge);
948 fuzz::<_, 9, 7>(10, &ge);
949 fuzz::<_, 10, 7>(10, &ge);
950 fuzz::<_, 11, 7>(10, &ge);
951 fuzz::<_, 12, 7>(10, &ge);
952 fuzz::<_, 13, 7>(10, &ge);
953 fuzz::<_, 14, 7>(10, &ge);
954 fuzz::<_, 15, 7>(10, &ge);
955 fuzz::<_, 16, 7>(10, &ge);
956 }
957
958 #[test]
959 fn test_fuzz_ge_full() {
960 let ge = |a: &i8, b: &i8, _: &()| a >= b;
961 fuzz::<_, 0, 4>(10, &ge);
962 fuzz::<_, 1, 4>(10, &ge);
963 fuzz::<_, 2, 4>(10, &ge);
964 fuzz::<_, 3, 4>(10, &ge);
965 fuzz::<_, 8, 16>(10, &ge);
966 fuzz::<_, 9, 16>(10, &ge);
967 fuzz::<_, 10, 16>(10, &ge);
968 fuzz::<_, 11, 16>(10, &ge);
969 fuzz::<_, 12, 16>(10, &ge);
970 fuzz::<_, 13, 16>(10, &ge);
971 fuzz::<_, 14, 16>(10, &ge);
972 fuzz::<_, 15, 16>(10, &ge);
973 }
974
975 fn fuzz<F, const N: usize, const M: usize>(iters: usize, comparer: &F)
976 where
977 F: Fn(&i8, &i8, &()) -> bool,
978 {
979 for _ in 0..iters {
980 let mut heap: FixedHeap<i8, N> = FixedHeap::new();
981 let mut array = [0i8; M];
982 rand::thread_rng().fill(&mut array[..]);
983 for element in array {
984 heap.push(element, comparer, &());
985 }
986 array.sort_by(|a, b| b.cmp(a));
987 for &element in array.iter().take(N) {
988 assert_eq!(Some(element), heap.pop(comparer, &()));
989 }
990 assert_eq!(None, heap.pop(comparer, &()));
991 }
992 }
993
994 #[test]
995 fn test_fuzz_true() {
996 let comparer = |_: &usize, _: &usize, _: &()| true;
997 fuzz_state::<_, _, 0, 4>(&comparer, &());
998 fuzz_state::<_, _, 1, 4>(&comparer, &());
999 fuzz_state::<_, _, 2, 4>(&comparer, &());
1000 fuzz_state::<_, _, 3, 4>(&comparer, &());
1001 fuzz_state::<_, _, 8, 16>(&comparer, &());
1002 fuzz_state::<_, _, 9, 16>(&comparer, &());
1003 fuzz_state::<_, _, 10, 16>(&comparer, &());
1004 fuzz_state::<_, _, 11, 16>(&comparer, &());
1005 fuzz_state::<_, _, 12, 16>(&comparer, &());
1006 fuzz_state::<_, _, 13, 16>(&comparer, &());
1007 fuzz_state::<_, _, 14, 16>(&comparer, &());
1008 fuzz_state::<_, _, 15, 16>(&comparer, &());
1009 fuzz_state::<_, _, 16, 16>(&comparer, &());
1010 fuzz_state::<_, _, 17, 16>(&comparer, &());
1011 }
1012
1013 #[test]
1014 fn test_fuzz_false() {
1015 let comparer = |_: &usize, _: &usize, _: &()| false;
1016 fuzz_state::<_, _, 0, 4>(&comparer, &());
1017 fuzz_state::<_, _, 1, 4>(&comparer, &());
1018 fuzz_state::<_, _, 2, 4>(&comparer, &());
1019 fuzz_state::<_, _, 3, 4>(&comparer, &());
1020 fuzz_state::<_, _, 8, 16>(&comparer, &());
1021 fuzz_state::<_, _, 9, 16>(&comparer, &());
1022 fuzz_state::<_, _, 10, 16>(&comparer, &());
1023 fuzz_state::<_, _, 11, 16>(&comparer, &());
1024 fuzz_state::<_, _, 12, 16>(&comparer, &());
1025 fuzz_state::<_, _, 13, 16>(&comparer, &());
1026 fuzz_state::<_, _, 14, 16>(&comparer, &());
1027 fuzz_state::<_, _, 15, 16>(&comparer, &());
1028 fuzz_state::<_, _, 16, 16>(&comparer, &());
1029 fuzz_state::<_, _, 17, 16>(&comparer, &());
1030 }
1031
1032 #[test]
1033 fn test_fuzz() {
1034 let rng = RefCell::new(rand::thread_rng());
1035 fn comparer(_: &usize, _: &usize, rng: &RefCell<ThreadRng>) -> bool {
1036 rng.borrow_mut().gen()
1037 }
1038 fuzz_state::<_, _, 0, 4>(&comparer, &rng);
1039 fuzz_state::<_, _, 1, 4>(&comparer, &rng);
1040 fuzz_state::<_, _, 2, 4>(&comparer, &rng);
1041 fuzz_state::<_, _, 3, 4>(&comparer, &rng);
1042 fuzz_state::<_, _, 8, 16>(&comparer, &rng);
1043 fuzz_state::<_, _, 9, 16>(&comparer, &rng);
1044 fuzz_state::<_, _, 10, 16>(&comparer, &rng);
1045 fuzz_state::<_, _, 11, 16>(&comparer, &rng);
1046 fuzz_state::<_, _, 12, 16>(&comparer, &rng);
1047 fuzz_state::<_, _, 13, 16>(&comparer, &rng);
1048 fuzz_state::<_, _, 14, 16>(&comparer, &rng);
1049 fuzz_state::<_, _, 15, 16>(&comparer, &rng);
1050 fuzz_state::<_, _, 16, 16>(&comparer, &rng);
1051 fuzz_state::<_, _, 17, 16>(&comparer, &rng);
1052 }
1053
1054 fn fuzz_state<S, F, const N: usize, const M: usize>(
1055 comparer: &F,
1056 state: &S,
1057 ) -> [Option<usize>; M]
1058 where
1059 F: Fn(&usize, &usize, &S) -> bool,
1060 {
1061 let mut heap: FixedHeap<usize, N> = FixedHeap::new();
1062 for i in 0..M {
1063 heap.push(i, comparer, state);
1064 }
1065 let mut result = [None; M];
1066 for item in result.iter_mut() {
1067 *item = heap.pop(comparer, state);
1068 }
1069 if N < M {
1070 for &item in result.iter().skip(N) {
1071 assert_eq!(None, item);
1072 }
1073 } else {
1074 assert_eq!(None, heap.pop(comparer, state));
1075 }
1076 result
1077 }
1078}