1use crate::size_hint;
2
3use alloc::vec::Vec;
4use std::fmt;
5use std::iter::FusedIterator;
6use std::mem::replace;
7
8#[derive(Debug)]
16struct HeadTail<I>
17where
18 I: Iterator,
19{
20 head: I::Item,
21 tail: I,
22}
23
24impl<I> HeadTail<I>
25where
26 I: Iterator,
27{
28 fn new(mut it: I) -> Option<Self> {
30 let head = it.next();
31 head.map(|h| Self { head: h, tail: it })
32 }
33
34 fn next(&mut self) -> Option<I::Item> {
38 if let Some(next) = self.tail.next() {
39 Some(replace(&mut self.head, next))
40 } else {
41 None
42 }
43 }
44
45 fn size_hint(&self) -> (usize, Option<usize>) {
47 size_hint::add_scalar(self.tail.size_hint(), 1)
48 }
49}
50
51impl<I> Clone for HeadTail<I>
52where
53 I: Iterator + Clone,
54 I::Item: Clone,
55{
56 clone_fields!(head, tail);
57}
58
59fn heapify<T, S>(data: &mut [T], mut less_than: S)
61where
62 S: FnMut(&T, &T) -> bool,
63{
64 for i in (0..data.len() / 2).rev() {
65 sift_down(data, i, &mut less_than);
66 }
67}
68
69fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
71where
72 S: FnMut(&T, &T) -> bool,
73{
74 debug_assert!(index <= heap.len());
75 let mut pos = index;
76 let mut child = 2 * pos + 1;
77 while child + 1 < heap.len() {
81 child += less_than(&heap[child + 1], &heap[child]) as usize;
84
85 if !less_than(&heap[child], &heap[pos]) {
87 return;
88 }
89 heap.swap(pos, child);
90 pos = child;
91 child = 2 * pos + 1;
92 }
93 if child + 1 == heap.len() && less_than(&heap[child], &heap[pos]) {
96 heap.swap(pos, child);
97 }
98}
99
100pub type KMerge<I> = KMergeBy<I, KMergeByLt>;
107
108pub trait KMergePredicate<T> {
109 fn kmerge_pred(&mut self, a: &T, b: &T) -> bool;
110}
111
112#[derive(Clone, Debug)]
113pub struct KMergeByLt;
114
115impl<T: PartialOrd> KMergePredicate<T> for KMergeByLt {
116 fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
117 a < b
118 }
119}
120
121impl<T, F: FnMut(&T, &T) -> bool> KMergePredicate<T> for F {
122 fn kmerge_pred(&mut self, a: &T, b: &T) -> bool {
123 self(a, b)
124 }
125}
126
127pub 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 self.heap
227 .iter()
228 .map(|i| i.size_hint())
229 .reduce(size_hint::add)
230 .unwrap_or((0, Some(0)))
231 }
232}
233
234impl<I, F> FusedIterator for KMergeBy<I, F>
235where
236 I: Iterator,
237 F: KMergePredicate<I::Item>,
238{
239}