1
//! General functions for use in consensus calculations
2
//!
3
//! Eg with signatures like [`Aggregate::aggregate`]
4

            
5
use super::*;
6

            
7
/// Return the low median of the inputs
8
10
pub(super) fn low_median<'i, T: Ord + Clone + 'i, AC>(
9
10
    _context: ConsensusContextRefs<AC>,
10
10
    inputs: impl ComponentInVotes<&'i T>,
11
10
) -> Result<T, ConsensusError> {
12
50
    low_median_raw(inputs.map(|(_vnum, v)| v.clone())).ok_or(ConsensusError::NoVotes)
13
10
}
14

            
15
/// Return the low median of the inputs, without cloning, and without context
16
106
pub(super) fn low_median_raw<'i, T: Ord + 'i>(inputs: impl Iterator<Item = T>) -> Option<T> {
17
106
    let mut all = inputs.collect_vec();
18
106
    all.sort();
19
106
    let i = all.len().checked_sub(1)? / 2;
20
105
    all.into_iter().nth(i)
21
106
}
22

            
23
#[cfg(test)]
24
mod test {
25
    // @@ begin test lint list maintained by maint/add_warning @@
26
    #![allow(clippy::bool_assert_comparison)]
27
    #![allow(clippy::clone_on_copy)]
28
    #![allow(clippy::dbg_macro)]
29
    #![allow(clippy::mixed_attributes_style)]
30
    #![allow(clippy::print_stderr)]
31
    #![allow(clippy::print_stdout)]
32
    #![allow(clippy::single_char_pattern)]
33
    #![allow(clippy::unwrap_used)]
34
    #![allow(clippy::unchecked_time_subtraction)]
35
    #![allow(clippy::useless_vec)]
36
    #![allow(clippy::needless_pass_by_value)]
37
    #![allow(clippy::string_slice)] // See arti#2571
38
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
39
    use super::*;
40

            
41
    #[test]
42
    fn low_medians() {
43
        let check = |exp: i32, inp: &[i32]| {
44
            assert_eq!(low_median_raw(inp.iter().cloned()), Some(exp), "{inp:?}");
45
        };
46

            
47
        assert_eq!(low_median_raw::<i32>([].into_iter()), None);
48
        check(1, &[1]);
49
        check(1, &[1, 2]);
50
        check(2, &[1, 2, 3]);
51
        check(2, &[1, 2, 3, 4]);
52
        check(3, &[1, 2, 3, 4, 5]);
53
    }
54
}