iter_merge/internal.rs
1//! Internal implementation details of this library.
2//!
3//! Typically you shouldn't need to touch these types, unless you're implementing another
4//! storage backend for iter-merge.
5//!
6//! [`PeekIter`] holds an iterator and the eagerly peeked item from it. The iterator with the
7//! smallest (according to the [`comparator`](crate::comparators)) [`item`](PeekIter::item)
8//! will be advanced.
9//!
10//! [`PeekIter`]s are stored within some contiguous allocation of `MaybeUninit<PeekIter>` type in
11//! order of insertion (to make [`tie breakers`](crate::comparators::tie_breaker) work by comparing
12//! `&PeekIter::item` by numeric pointer value).
13//!
14//! The heap is a contiguous allocation of `*mut PeekIter` type. Pointers in the heap represent
15//! all currently live `PeekIter`s. This library only works with the heap via [`BaseStorage`] trait.
16//!
17//! Heap is constructed to store `*mut PeekIter`s in the following order:
18//! ```custom
19//! [
20//! smallest,
21//! second_smallest (also the root of the binary min-heap),
22//! second_smallest_child_1, second_smallest_child_2,
23//! ...
24//! ]
25//! ```
26mod heap;
27use core::mem;
28pub(crate) mod nums;
29pub(crate) mod pointers;
30
31pub(crate) use heap::Heap;
32mod hole;
33pub(crate) use hole::Hole;
34
35/// Holds within itself one peeked item from the iterator and the iterator itself.
36/// It's like [`iter::Peekable`](core::iter::Peekable), except eager.
37#[derive(Debug)]
38pub struct PeekIter<IT: Iterator> {
39 /// Item peeked from the iter
40 pub item: IT::Item,
41 /// Iterator, containing the rest of the items
42 pub iter: IT,
43}
44
45impl<IT> Clone for PeekIter<IT>
46where
47 IT: Iterator + Clone,
48 IT::Item: Clone,
49{
50 fn clone(&self) -> Self {
51 Self {
52 item: self.item.clone(),
53 iter: self.iter.clone(),
54 }
55 }
56}
57
58impl<IT: Iterator> PeekIter<IT> {
59 const _CHECK: () = assert!(
60 mem::size_of::<Self>() > 0,
61 "iter-merge doesn't work when both iterator and item are ZST",
62 );
63
64 /// Create a new [`PeekIter`] from a `peeked_item` and `iter`
65 #[inline]
66 pub const fn new(peeked_item: IT::Item, iter: IT) -> Self {
67 Self {
68 item: peeked_item,
69 iter,
70 }
71 }
72
73 /// Advances the iterator, returning current peeked [`item`](Self::item) and replacing it
74 /// with new item from the [`iter`](Self::iter). If `iter` is out of items - returns None,
75 /// with [`item`](Self::item) being the last item of the iterator.
76 pub fn advance(&mut self) -> Option<IT::Item> {
77 let Self { item, iter } = self;
78 iter.next().map(|new_item| mem::replace(item, new_item))
79 }
80
81 /// Create a new [`PeekIter`] from an `iter`
82 ///
83 /// If the iterator is empty - returns None.
84 pub fn new_from_iter<Iter>(iter: Iter) -> Option<Self>
85 where
86 Iter: IntoIterator<IntoIter = IT>,
87 {
88 let mut iter = iter.into_iter();
89 iter.next()
90 .map(move |peeked_item| Self::new(peeked_item, iter))
91 }
92}
93
94/// Trait implemented by all storage backends.
95///
96/// # Invariant
97/// Assuming no external mutation of pointers or length, after any call to this library first
98/// [`len`](BaseStorage::len) elements of [`heap`](BaseStorage::heap) are valid unique pointers to
99/// valid [`PeekIter`] items.
100///
101/// In other words, [`heap`](BaseStorage::heap) upholds all of the properties to be treated as a
102/// slice `&[&mut PeekIter]` with length [`len`](BaseStorage::len)
103///
104/// # Safety
105/// Storage (conceptually) represents an owned array of [`PeekIter<IT: Iterator>`] with length
106/// `len()`, that could be accessed indirectly via heap of `*mut PeekIter` with length
107/// [`len`](BaseStorage::len).
108///
109/// Simple way to satisfy all these contracts:
110/// * allocate and fill `[PeekIter; CAP]`, do not access or create references until `drop()`;
111/// make sure that this allocation could not move (pinned) until the `drop()`
112/// * allocate `[*mut PeekIter; CAP]` and fill it with pointers to previous
113/// allocation, do not access or create references until drop, make sure that this allocation
114/// could not move (pinned) until the `drop()`
115/// * Provide access to the second allocation as [`BaseStorage::heap`], and to its length as
116/// [`BaseStorage::len`], initially equal to `CAP`
117/// * In `Drop`:
118/// * deallocate the remaining live [`PeekIter`]s via call to
119/// [`StorageOps::clear()`](crate::internal::StorageOps::clear)
120/// * deallocate heap and storage, assuming that they are uninitialized, with the same initial
121/// capacity
122/// (`[MaybeUninit<*mut PeekIter>; CAP]` and `[MaybeUninit<PeekIter>; CAP]`)
123#[allow(clippy::len_without_is_empty)]
124pub unsafe trait BaseStorage {
125 /// Iterator contained in this storage
126 type IT: Iterator;
127
128 /// Pointer to the heap of pointers
129 fn heap(&self) -> *mut *mut PeekIter<Self::IT>;
130
131 /// Length of the heap of pointers
132 fn len(&self) -> usize;
133
134 /// Set the length of the storage
135 /// # Safety
136 /// Caller guarantees that heap elements in `self.len()..new_len` are initialized
137 unsafe fn set_len(&mut self, new_len: usize);
138
139 /// Returns true if [`Self::len`](crate::internal::BaseStorage::len) == 0
140 #[inline]
141 fn is_empty(&self) -> bool {
142 self.len() == 0
143 }
144}
145
146/// Provides access to the iterator type within the storage
147pub type Iter<S> = <S as BaseStorage>::IT;
148/// Provides access to the iterator's item type within the storage
149pub type Item<S> = <Iter<S> as Iterator>::Item;
150
151/// Extra methods for working with [`BaseStorage`] for this library
152///
153/// It is implemented automatically for all implementors of [`BaseStorage`]
154pub trait StorageOps: BaseStorage {
155 /// Decrements length by 1 and returns the new length.
156 /// Does nothing to the last item, so
157 /// `self.heap().add(self.dec_len())` is still a valid pointer to a live item,
158 /// but you are guaranteed that this trait will never return it again (if safety contracts
159 /// are not broken)
160 /// # Safety
161 /// Caller guarantees that `self.len()` > 0
162 #[inline]
163 unsafe fn dec_len(&mut self) -> usize {
164 let mut len = self.len();
165 debug_assert!(len != 0);
166 len = len.wrapping_sub(1);
167 // SAFETY: decreasing length is safe, caller guaranteed that len != 0
168 unsafe {
169 self.set_len(len);
170 }
171 len
172 }
173
174 /// Produces pointer to the first (smallest) item
175 /// Pointers are valid, initialized and unique
176 /// It's valid to treat them as mut refs if no other
177 /// mut refs to the `first()` exist.
178 /// # Safety
179 /// Caller guarantees that `len()` >= 1
180 #[inline]
181 unsafe fn first(&self) -> *mut *mut PeekIter<Self::IT> {
182 debug_assert!(self.len() >= 1);
183 self.heap()
184 }
185
186 /// Produces pointer to the second (second-smallest) item
187 /// which is also the root of the binary heap.
188 /// Pointers are valid, initialized and unique
189 /// It's valid to treat them as mut refs if no other
190 /// mut refs to the `second()` exist.
191 /// # Safety
192 /// Caller guarantees that `len()` >= 2
193 #[inline]
194 unsafe fn second(&self) -> *mut *mut PeekIter<Self::IT> {
195 debug_assert!(self.len() >= 2);
196 // SAFETY: caller guarantees it's safe
197 unsafe { self.heap().add(1) }
198 }
199
200 /// Produces pointer to the last item in the heap and decrements its length
201 /// by 1.
202 /// Pointers are valid, initialized and unique
203 /// It's valid to treat them as mut refs.
204 /// # Safety
205 /// Caller guarantees that `len()` != 0.
206 /// The operation will produce the same pointer as
207 /// `first()` or `second()` if `len()` is 1 or 2.
208 #[inline]
209 unsafe fn pop_last(&mut self) -> *mut PeekIter<Self::IT> {
210 debug_assert!(self.len() != 0);
211 // SAFETY: caller guarantees it's safe
212 unsafe { self.heap().add(self.dec_len()).read() }
213 }
214
215 /// Drops all remaining items in the storage and sets its length to 0.
216 /// It's safe to call multiple times (repeated calls are no-ops)
217 fn clear(&mut self) {
218 let len = self.len();
219 // SAFETY: decreasing length is safe
220 unsafe {
221 self.set_len(0);
222 }
223 for i in 0..len {
224 // SAFETY: this operations are valid for `len` heap items
225 unsafe {
226 self.heap().add(i).read().drop_in_place();
227 };
228 }
229 }
230
231 /// Iterates over all items in the heap and calls `func` for each
232 /// Only the first two items are in order, order of the rest is *unspecified*.
233 #[inline]
234 fn map_items(&self, mut func: impl FnMut(&PeekIter<Self::IT>)) {
235 for i in 0..self.len() {
236 func(
237 // SAFETY: pointers up to self.len() are valid
238 unsafe { &**self.heap().add(i) },
239 );
240 }
241 }
242
243 /// Peeks the first item of the heap
244 #[inline]
245 fn peek(&self) -> Option<&Item<Self>> {
246 if self.is_empty() {
247 return None;
248 }
249 // SAFETY: len >= 1
250 Some(unsafe { &(**self.first()).item })
251 }
252
253 /// Pops the last item+iterator tuple in the heap (no order guaranteed, heap structure is preserved)
254 #[inline]
255 fn pop_last_item(&mut self) -> Option<(Item<Self>, Self::IT)> {
256 if self.is_empty() {
257 return None;
258 }
259 // SAFETY: self.len() != 0, heap items are valid
260 let PeekIter { item, iter } = unsafe { self.heap().add(self.dec_len()).read().read() };
261 Some((item, iter))
262 }
263}
264
265impl<S: BaseStorage> StorageOps for S {}