dwd 0.5.0

High performance traffic generator
Documentation
use core::{
    fmt,
    fmt::{Display, Formatter},
};
use std::time::Instant;

use super::Metric;

pub struct Throughput {
    f: Box<dyn Fn() -> u64 + Send>,
    prev_v: u64,
    prev_ts: Instant,
    value: (f64, char),
}

impl Throughput {
    pub fn new<F, S>(f: F, stat: S) -> Self
    where
        F: Fn(&S) -> u64 + Send + 'static,
        S: Send + 'static,
    {
        Self {
            f: Box::new(move || f(&stat)),
            prev_v: 0,
            prev_ts: Instant::now(),
            value: (0.0, ' '),
        }
    }

    fn fmt_si(v: f64) -> (f64, char) {
        match v {
            v if v >= 1e9 => (v / 1e9, 'G'),
            v if v >= 1e6 => (v / 1e6, 'M'),
            v if v >= 1e3 => (v / 1e3, 'K'),
            _ => (v, ' '),
        }
    }
}

impl Display for Throughput {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        let (rate, prefix) = self.value;

        write!(f, "{:.2} {}bit/s", rate, prefix)
    }
}

impl Metric for Throughput {
    fn update(&mut self) {
        let now = Instant::now();

        let v = (self.f)();
        let dv = (v.saturating_sub(self.prev_v) * 8) as f64;
        let dt = now.duration_since(self.prev_ts).as_secs_f64();
        let rate = dv / dt;

        self.prev_v = v;
        self.prev_ts = now;

        self.value = Self::fmt_si(rate);
    }
}