extern crate time;
use std::fmt::{Formatter, Display, Error};
use std::sync::Mutex;
#[derive(Debug,Clone,Copy,Eq,PartialEq,PartialOrd,Ord)]
pub struct HLTimespec {
wall: time::Timespec,
logical: u16,
}
impl HLTimespec {
pub fn new(s: i64, ns: i32, l: u16) -> HLTimespec {
HLTimespec { wall: time::Timespec { sec: s, nsec: ns }, logical: l }
}
}
impl Display for HLTimespec {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.write_str(&format!("{}.{}+{}", self.wall.sec, self.wall.nsec, self.logical))
}
}
pub struct State<F> {
s: HLTimespec,
now: F,
}
impl State<()> {
pub fn new() -> State<fn() -> time::Timespec> {
State::new_with(time::get_time)
}
pub fn new_sendable() -> Mutex<State<fn() -> time::Timespec>> {
Mutex::new(State::new())
}
}
impl<F: FnMut() -> time::Timespec> State<F> {
pub fn new_with(now: F) -> State<F> {
State {
s: HLTimespec { wall: time::Timespec { sec: 0, nsec: 0 }, logical: 0 },
now: now,
}
}
pub fn get_time(&mut self) -> HLTimespec {
let s = &mut self.s;
let wall = (self.now)();
if s.wall < wall {
s.wall = wall;
s.logical = 0;
} else {
s.logical += 1;
}
s.clone()
}
pub fn update(&mut self, event: HLTimespec) -> HLTimespec {
let (wall, s) = ((self.now)(), &mut self.s);
if wall > event.wall && wall > s.wall {
s.wall = wall;
s.logical = 0
} else if event.wall > s.wall {
s.wall = event.wall;
s.logical = event.logical+1;
} else if s.wall > event.wall {
s.logical += 1;
} else {
if event.logical > s.logical {
s.logical = event.logical;
}
s.logical += 1;
}
s.clone()
}
}
#[cfg(test)]
mod tests {
extern crate time;
use {HLTimespec, State};
fn ts(s: i64, ns: i32) -> time::Timespec {
time::Timespec { sec: s, nsec: ns }
}
fn hlts(s: i64, ns: i32, l: u16) -> HLTimespec {
HLTimespec::new(s, ns, l)
}
#[test]
fn it_works() {
let zero = hlts(0, 0, 0);
let ops = vec![
(ts(1,0), zero, hlts(1,0,0)),
(ts(1,0), zero, hlts(1,0,1)), (ts(0,9), zero, hlts(1,0,2)), (ts(2,0), zero, hlts(2,0,0)), (ts(3,0), hlts(1,2,3), hlts(3,0,0)), (ts(3,0), hlts(1,2,3), hlts(3,0,1)), (ts(3,0), hlts(3,0,1), hlts(3,0,2)), (ts(3,0), hlts(3,0,99), hlts(3,0,100)), (ts(3,5), hlts(4,4,100), hlts(4,4,101)), (ts(5,0), hlts(4,5,0), hlts(5,0,0)), (ts(4,9), hlts(5,0,99), hlts(5,0,100)),
(ts(0,0), hlts(5,0,50), hlts(5,0,101)), ];
let mut times = ops.iter().rev().map(|op| op.0).collect::<Vec<time::Timespec>>();
let mut s = State::new_with(move || times.pop().unwrap());
for op in &ops {
let t = if op.1 == zero {
s.get_time()
} else {
s.update(op.1.clone())
};
assert_eq!(t, op.2);
}
}
}