bump_scope/polyfill/
iter.rs

1#![expect(clippy::pedantic)]
2#![expect(clippy::toplevel_ref_arg)]
3
4/// See [`std::iter::Iterator::partition_in_place`].
5pub(crate) fn partition_in_place<'a, T: 'a, P>(
6    mut iter: impl DoubleEndedIterator<Item = &'a mut T>,
7    ref mut predicate: P,
8) -> usize
9where
10    P: FnMut(&T) -> bool,
11{
12    // STD-FIXME: should we worry about the count overflowing? The only way to have more than
13    // `usize::MAX` mutable references is with ZSTs, which aren't useful to partition...
14
15    // These closure "factory" functions exist to avoid genericity in `Self`.
16
17    #[inline]
18    fn is_false<'a, T>(
19        predicate: &'a mut impl FnMut(&T) -> bool,
20        true_count: &'a mut usize,
21    ) -> impl FnMut(&&mut T) -> bool + 'a {
22        move |x| {
23            let p = predicate(&**x);
24            *true_count += p as usize;
25            !p
26        }
27    }
28
29    #[inline]
30    fn is_true<T>(predicate: &mut impl FnMut(&T) -> bool) -> impl FnMut(&&mut T) -> bool + '_ {
31        move |x| predicate(&**x)
32    }
33
34    // Repeatedly find the first `false` and swap it with the last `true`.
35    let mut true_count = 0;
36    while let Some(head) = iter.find(is_false(predicate, &mut true_count)) {
37        if let Some(tail) = iter.rfind(is_true(predicate)) {
38            crate::mem::swap(head, tail);
39            true_count += 1;
40        } else {
41            break;
42        }
43    }
44    true_count
45}