1use crate::size_hint;
2use crate::Itertools;
3
4use alloc::vec::Vec;
5use std::fmt;
6use std::iter::FusedIterator;
7use std::mem::replace;
8
9#[derive(Debug)]
17struct HeadTail<I>
18where
19    I: Iterator,
20{
21    head: I::Item,
22    tail: I,
23}
24
25impl<I> HeadTail<I>
26where
27    I: Iterator,
28{
29    fn new(mut it: I) -> Option<Self> {
31        let head = it.next();
32        head.map(|h| Self { head: h, tail: it })
33    }
34
35    fn next(&mut self) -> Option<I::Item> {
39        if let Some(next) = self.tail.next() {
40            Some(replace(&mut self.head, next))
41        } else {
42            None
43        }
44    }
45
46    fn size_hint(&self) -> (usize, Option<usize>) {
48        size_hint::add_scalar(self.tail.size_hint(), 1)
49    }
50}
51
52impl<I> Clone for HeadTail<I>
53where
54    I: Iterator + Clone,
55    I::Item: Clone,
56{
57    clone_fields!(head, tail);
58}
59
60fn heapify<T, S>(data: &mut [T], mut less_than: S)
62where
63    S: FnMut(&T, &T) -> bool,
64{
65    for i in (0..data.len() / 2).rev() {
66        sift_down(data, i, &mut less_than);
67    }
68}
69
70fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
72where
73    S: FnMut(&T, &T) -> bool,
74{
75    debug_assert!(index <= heap.len());
76    let mut pos = index;
77    let mut child = 2 * pos + 1;
78    while child + 1 < heap.len() {
82        child += less_than(&heap[child + 1], &heap[child]) as usize;
85
86        if !less_than(&heap[child], &heap[pos]) {
88            return;
89        }
90        heap.swap(pos, child);
91        pos = child;
92        child = 2 * pos + 1;
93    }
94    if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) {
97        heap.swap(pos, child);
98    }
99}
100
101pub type KMerge<I> = KMergeBy<I, KMergeByLt>;
108
109pub trait KMergePredicate<T> {
110    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
111}
112
113#[derive(Clone, Debug)]
114pub struct KMergeByLt;
115
116impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
117    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
118        a < b
119    }
120}
121
122impl<T, F: FnMut(&T, &T) -> bool> KMergePredicate<T> for F {
123    fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
124        self(a, b)
125    }
126}
127
128pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
141where
142    I: IntoIterator,
143    I::Item: IntoIterator,
144    <<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd,
145{
146    kmerge_by(iterable, KMergeByLt)
147}
148
149#[must_use = "this iterator adaptor is not lazy but does nearly nothing unless consumed"]
157pub struct KMergeBy<I, F>
158where
159    I: Iterator,
160{
161    heap: Vec<HeadTail<I>>,
162    less_than: F,
163}
164
165impl<I, F> fmt::Debug for KMergeBy<I, F>
166where
167    I: Iterator + fmt::Debug,
168    I::Item: fmt::Debug,
169{
170    debug_fmt_fields!(KMergeBy, heap);
171}
172
173pub fn kmerge_by<I, F>(
177    iterable: I,
178    mut less_than: F,
179) -> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
180where
181    I: IntoIterator,
182    I::Item: IntoIterator,
183    F: KMergePredicate<<<I as IntoIterator>::Item as IntoIterator>::Item>,
184{
185    let iter = iterable.into_iter();
186    let (lower, _) = iter.size_hint();
187    let mut heap: Vec<_> = Vec::with_capacity(lower);
188    heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
189    heapify(&mut heap, |a, b| less_than.kmerge_pred(&a.head, &b.head));
190    KMergeBy { heap, less_than }
191}
192
193impl<I, F> Clone for KMergeBy<I, F>
194where
195    I: Iterator + Clone,
196    I::Item: Clone,
197    F: Clone,
198{
199    clone_fields!(heap, less_than);
200}
201
202impl<I, F> Iterator for KMergeBy<I, F>
203where
204    I: Iterator,
205    F: KMergePredicate<I::Item>,
206{
207    type Item = I::Item;
208
209    fn next(&mut self) -> Option<Self::Item> {
210        if self.heap.is_empty() {
211            return None;
212        }
213        let result = if let Some(next) = self.heap[0].next() {
214            next
215        } else {
216            self.heap.swap_remove(0).head
217        };
218        let less_than = &mut self.less_than;
219        sift_down(&mut self.heap, 0, |a, b| {
220            less_than.kmerge_pred(&a.head, &b.head)
221        });
222        Some(result)
223    }
224
225    fn size_hint(&self) -> (usize, Option<usize>) {
226        #[allow(deprecated)] self.heap
228            .iter()
229            .map(|i| i.size_hint())
230            .fold1(size_hint::add)
231            .unwrap_or((0, Some(0)))
232    }
233}
234
235impl<I, F> FusedIterator for KMergeBy<I, F>
236where
237    I: Iterator,
238    F: KMergePredicate<I::Item>,
239{
240}