#![feature(try_from)]
#[macro_use]
extern crate serde_derive;
extern crate serde;
use std::convert::TryInto;
use std::time::{UNIX_EPOCH, Duration, SystemTime};
const DELTA_1970_1900: u32 = (70*365 + 17)*86400;
pub trait OscMessage<'m> : serde::Serialize + serde::Deserialize<'m> {
fn build_address(&self, string: &mut String);
fn get_address(&self) -> String {
let mut s = String::new();
self.build_address(&mut s);
s
}
fn serialize_body<S: serde::ser::SerializeTuple>(&self, serializer: &mut S) -> Result<(), S::Error>;
fn deserialize_body<D: serde::de::SeqAccess<'m>>(address: String, seq: D) -> Result<Self, D::Error>;
}
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
pub struct OscBundle<M> {
time_tag: (u32, u32),
messages: Vec<OscPacket<M>>,
}
#[derive(Debug)]
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum OscPacket<M> {
Message(M),
Bundle(OscBundle<M>),
}
#[derive(Copy, Clone, Debug)]
pub enum OscTime {
Now,
At(AbsOscTime),
}
#[derive(Copy, Clone, Debug)]
pub struct AbsOscTime {
sec: u32,
frac: u32,
}
impl<M> OscBundle<M> {
pub fn time_tag(&self) -> OscTime {
OscTime::new(self.time_tag.0, self.time_tag.1)
}
pub fn messages(&self) -> &Vec<OscPacket<M>> {
&self.messages
}
}
impl OscTime {
pub fn new(sec: u32, frac: u32) -> Self {
match (sec, frac) {
(0, 1) => OscTime::Now,
_ => OscTime::At(AbsOscTime::new(sec, frac)),
}
}
pub fn as_system_time(&self) -> Option<SystemTime> {
match *self {
OscTime::At(ref abs_time) => abs_time.as_system_time(),
OscTime::Now => Some(SystemTime::now()),
}
}
}
impl AbsOscTime {
pub fn new(sec: u32, frac: u32) -> Self {
Self{ sec, frac }
}
pub fn from_system_time(t: SystemTime) -> Option<Self> {
let since_epoch = t.duration_since(UNIX_EPOCH);
let since_epoch = match since_epoch {
Err(_) => return None,
Ok(dur) => dur,
};
let unix_secs: Result<u32, _> = since_epoch.as_secs().try_into();
let unix_secs = match unix_secs {
Err(_) => return None,
Ok(secs) => secs,
};
let ntp_secs = unix_secs.checked_add(DELTA_1970_1900);
ntp_secs.map(|ntp_secs| {
let frac = ((since_epoch.subsec_nanos() as u64) << 32) / 1000000000;
Self::new(ntp_secs, frac as u32)
})
}
pub fn sec(&self) -> u32 {
self.sec
}
pub fn frac(&self) -> u32 {
self.frac
}
pub fn sec_frac(&self) -> (u32, u32) {
(self.sec, self.frac)
}
pub fn as_system_time(&self) -> Option<SystemTime> {
let secs_unix = self.sec().checked_sub(DELTA_1970_1900);
secs_unix.map(|secs_unix| {
let nanos = (self.frac() as u64 * 1000000000) >> 32;
UNIX_EPOCH + Duration::new(secs_unix as u64, nanos as u32)
})
}
}