pub struct Stats { /// Number of received packets (better names: `packets_received` or `received_count`) pub received: usize, /// Number of lost packets (total - received) (better names: `packets_lost` or `lost_count`) pub lost: usize, // Round-Time Trip pub min_rtt: u64, pub max_rtt: u64, pub avg_rtt: f64, /// Mean absolute difference (deviation) from the average pub mad_rtt: f64, } pub fn compute_stats(states: &[crate::state::State]) -> Option { let mut rtts: Vec = Vec::new(); let received = states .iter() .filter(|state| matches!(state, crate::state::State::Received { .. } | crate::state::State::NotYetReceived { .. } )) .count(); let lost = states.len() - received; if received == 0 { return None; } for state in states { if let crate::state::State::Received { rtt } = state { rtts.push(*rtt); } } // RTT stats let min_rtt = rtts.iter().min().copied().unwrap_or(0); let max_rtt = rtts.iter().max().copied().unwrap_or(0); let sum_rtt: u64 = rtts.iter().sum(); let avg_rtt = sum_rtt as f64 / rtts.len() as f64; let mad_rtt: f64 = rtts .iter() .map(|&x| (x as f64 - avg_rtt).abs()) .sum::() / rtts.len() as f64; Some(Stats { received, lost, min_rtt, max_rtt, avg_rtt, mad_rtt, }) }