use hifitime::TimeScale;
use thiserror::Error;
#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Leap {
pub leap: u32,
pub delta_tls: Option<u32>,
pub week: Option<u32>,
pub day: Option<u32>,
pub timescale: Option<TimeScale>,
}
#[derive(Error, Debug)]
pub enum Error {
#[error("failed to parse leap integer number")]
ParseIntError(#[from] std::num::ParseIntError),
#[error("failed to parse leap timescale")]
TimeScaleError(#[from] hifitime::Errors),
}
impl Leap {
pub fn new(
leap: u32,
delta_tls: Option<u32>,
week: Option<u32>,
day: Option<u32>,
timescale: Option<TimeScale>,
) -> Self {
Self {
leap,
delta_tls,
week,
day,
timescale,
}
}
}
impl std::str::FromStr for Leap {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut ls = Leap::default();
let items: Vec<&str> = s.split_ascii_whitespace().collect();
match items.len() > 2 {
false => {
ls.leap = items[0].trim().parse::<u32>()?;
},
true => {
let (leap, rem) = s.split_at(5);
let (tls, rem) = rem.split_at(5);
let (week, rem) = rem.split_at(5);
let (day, rem) = rem.split_at(5);
let system = rem.trim();
ls.leap = leap.trim().parse::<u32>()?;
ls.delta_tls = Some(tls.trim().parse::<u32>()?);
ls.week = Some(week.trim().parse::<u32>()?);
ls.day = Some(day.trim().parse::<u32>()?);
if system.eq("") {
ls.timescale = None
} else {
ls.timescale = Some(TimeScale::from_str(system)?)
}
},
}
Ok(ls)
}
}
#[cfg(test)]
mod test {
use super::*;
use std::str::FromStr;
#[test]
fn basic_format() {
let content = "18";
let leap = Leap::from_str(content);
assert!(leap.is_ok());
let leap = leap.unwrap();
assert_eq!(leap.leap, 18);
}
#[test]
fn standard_format() {
let content = "18 18 2185 7";
let leap = Leap::from_str(content);
assert!(leap.is_ok());
let leap = leap.unwrap();
assert_eq!(leap.leap, 18);
assert_eq!(leap.week, Some(2185));
assert_eq!(leap.day, Some(7));
}
#[test]
fn parse_with_timescale() {
let content = "18 18 2185 7GPS";
let leap = Leap::from_str(content);
assert!(leap.is_ok());
let leap = leap.unwrap();
assert_eq!(leap.leap, 18);
assert_eq!(leap.week, Some(2185));
assert_eq!(leap.day, Some(7));
}
}