msgpacknet 0.1.0

A networking layer based on MessagePack messages.
Documentation
use std::io::{self, Write, Read};
use std::time::Duration;
use std::sync::{Arc, RwLock};

use time;

fn now_as_float() -> f64 {
    let t = time::get_time();
    t.sec as f64 + t.nsec as f64 * 0.000000001
}

fn duration_as_float(dur: Duration) -> f64 {
    dur.as_secs() as f64 + dur.subsec_nanos() as f64 * 0.000000001
}

pub struct Stats {
    total: u64,
    rate: f64,
    last: f64,
    halftime: f64
}

impl Stats {
    pub fn new(halftime: Duration) -> Self {
        Stats{total: 0, rate: 0.0, last: now_as_float(), halftime: duration_as_float(halftime)}
    }

    pub fn update(&mut self, amount: usize) {
        self.total += amount as u64;
        let now = now_as_float();
        let alpha = 0.5f64.powf((now-self.last)/self.halftime);
        self.rate = self.rate * alpha + amount as f64 * (1.0f64 - alpha);
        self.last = now;
    }

    pub fn rate(&self) -> f64 {
        let now = now_as_float();
        let alpha = 0.5f64.powf((now-self.last)/self.halftime);
        self.rate * alpha
    }

    pub fn idle_time(&self) -> Duration {
        let diff = now_as_float() - self.last;
        Duration::new(diff.floor() as u64, ((diff - diff.floor())*1000000000.0) as u32)
    }

    pub fn total(&self) -> u64 {
        self.total
    }
}


pub struct StatWriter<T> {
    inner: T,
    stats: Arc<RwLock<Stats>>
}

impl<T> StatWriter<T> {
    pub fn new(inner: T, halflife: Duration) -> Self {
        StatWriter{inner: inner, stats: Arc::new(RwLock::new(Stats::new(halflife)))}
    }

    pub fn stats(&self) -> Arc<RwLock<Stats>> {
        self.stats.clone()
    }
}

impl<T: Write> Write for StatWriter<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let bytes = try!(self.inner.write(buf));
        self.stats.write().expect("Lock poisoned").update(bytes);
        Ok(bytes)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.inner.flush()
    }
}


pub struct StatReader<T> {
    inner: T,
    stats: Arc<RwLock<Stats>>
}

impl<T> StatReader<T> {
    pub fn new(inner: T, halflife: Duration) -> Self {
        StatReader{inner: inner, stats: Arc::new(RwLock::new(Stats::new(halflife)))}
    }

    pub fn stats(&self) -> Arc<RwLock<Stats>> {
        self.stats.clone()
    }
}

impl<T: Read> Read for StatReader<T> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let bytes = try!(self.inner.read(buf));
        self.stats.write().expect("Lock poisoned").update(bytes);
        Ok(bytes)
    }
}