use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Clock {
value: u64,
}
impl Clock {
pub fn base(stc: u64) -> Clock {
Clock { value: stc << 9 }
}
pub fn with_ext(&self, ext: u16) -> Clock {
Clock { value: self.value & !0x1f | u64::from(ext) }
}
pub fn to_seconds(&self) -> f64 {
let base = (self.value >> 9) as f64;
let ext = (self.value & 0x1F) as f64;
(base + ext / 300.0) / 90000.0
}
}
impl<'a> fmt::Display for Clock {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = self.to_seconds();
let h = (s / 3600.0).trunc();
s = s % 3600.0;
let m = (s / 60.0).trunc();
s = s % 60.0;
write!(f, "{}:{:02}:{:1.3}", h, m, s)
}
}
named!(pub clock<(&[u8], usize), Clock>,
do_parse!(
hi: take_bits!(u64, 3) >>
tag_bits!(u8, 1, 0b1) >>
mid: take_bits!(u64, 15) >>
tag_bits!(u8, 1, 0b1) >>
lo: take_bits!(u64, 15) >>
tag_bits!(u8, 1, 0b1) >>
(Clock::base(hi << 30 | mid << 15 | lo))
)
);
named!(pub clock_and_ext<(&[u8], usize), Clock>,
do_parse!(
clock: call!(clock) >>
ext: take_bits!(u16, 9) >>
tag_bits!(u8, 1, 0b1) >>
(clock.with_ext(ext))
)
);
#[test]
fn parse_clock() {
use nom::IResult;
assert_eq!(clock((&[0x44, 0x02, 0xc4, 0x82, 0x04][..], 2)),
IResult::Done((&[0x04][..], 6),
Clock::base(0b_000_000000001011000_001000001000000)));
assert_eq!(clock_and_ext((&[0x44, 0x02, 0xc4, 0x82, 0x04, 0xa9][..], 2)),
IResult::Done((&[][..], 0),
Clock::base(0b_000_000000001011000_001000001000000)
.with_ext(0b001010100)));
}