extern crate flate2;
extern crate regex;
extern crate serde;
extern crate serde_derive;
use self::regex::Regex;
use crate::time::{Epoch, SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MINUTE};
use std::fmt;
use std::str::FromStr;
pub mod gravity;
pub mod cosmo;
pub mod frame_serde;
pub mod rv;
pub mod scenario;
pub mod odp;
pub mod formatter;
#[derive(Debug)]
pub enum ParsingError {
MD(String),
OD(String),
UseOdInstead,
UseMdInstead,
EpochFormat,
CovarFormat,
FileNotFound(String),
FileNotUTF8(String),
FileUnreadable(String),
HarmonicsFile(String),
SequenceNotFound(String),
LoadingError(String),
PropagatorNotFound(String),
Duration(String),
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum EpochFormat {
GregorianUtc,
GregorianTai,
MjdTai,
MjdTt,
MjdUtc,
JdeEt,
JdeTai,
JdeTt,
JdeUtc,
TaiSecs(f64),
TaiDays(f64),
}
impl EpochFormat {
pub fn format(&self, dt: Epoch) -> String {
match *self {
EpochFormat::GregorianUtc => dt.as_gregorian_utc_str(),
EpochFormat::GregorianTai => dt.as_gregorian_tai_str(),
EpochFormat::MjdTai => format!("{:.9}", dt.as_mjd_tai_days()),
EpochFormat::MjdTt => format!("{:.9}", dt.as_mjd_tt_days()),
EpochFormat::MjdUtc => format!("{:.9}", dt.as_mjd_utc_days()),
EpochFormat::JdeEt => format!("{:.9}", dt.as_jde_et_days()),
EpochFormat::JdeTai => format!("{:.9}", dt.as_jde_tai_days()),
EpochFormat::JdeTt => format!("{:.9}", dt.as_jde_tt_days()),
EpochFormat::JdeUtc => format!("{:.9}", dt.as_jde_utc_days()),
EpochFormat::TaiSecs(e) => format!("{:.9}", dt.as_tai_seconds() - e),
EpochFormat::TaiDays(e) => format!("{:.9}", dt.as_tai_days() - e),
}
}
}
impl fmt::Display for EpochFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
EpochFormat::GregorianUtc => write!(f, "Gregorian UTC"),
EpochFormat::GregorianTai => write!(f, "Gregorian TAI"),
EpochFormat::MjdTai => write!(f, "MJD TAI"),
EpochFormat::MjdTt => write!(f, "MJD TT"),
EpochFormat::MjdUtc => write!(f, "MJD UTC"),
EpochFormat::JdeEt => write!(f, "JDE ET"),
EpochFormat::JdeTai => write!(f, "JDE TAI"),
EpochFormat::JdeTt => write!(f, "JDE TT"),
EpochFormat::JdeUtc => write!(f, "JDE UTC"),
EpochFormat::TaiSecs(_) => write!(f, "TAI+ s"),
EpochFormat::TaiDays(_) => write!(f, "TAI+ days"),
}
}
}
impl FromStr for EpochFormat {
type Err = ParsingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().replace(" ", "").as_str() {
"gregorianutc" => Ok(EpochFormat::GregorianUtc),
"gregoriantai" => Ok(EpochFormat::GregorianTai),
"mjdtai" => Ok(EpochFormat::MjdTai),
"mjdtt" => Ok(EpochFormat::MjdTt),
"mjdutc" => Ok(EpochFormat::MjdUtc),
"jdeet" => Ok(EpochFormat::JdeEt),
"jdetai" => Ok(EpochFormat::JdeTai),
"jdett" => Ok(EpochFormat::JdeTt),
"jdeutc" => Ok(EpochFormat::JdeUtc),
_ => Err(ParsingError::EpochFormat),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CovarFormat {
Sqrt,
Sigma1,
Sigma3,
MulSigma(f64),
}
impl fmt::Display for CovarFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CovarFormat::Sqrt => write!(f, "exptd_val_"),
CovarFormat::Sigma1 => write!(f, "covar_"),
CovarFormat::Sigma3 => write!(f, "3sig_covar"),
CovarFormat::MulSigma(x) => write!(f, "{}sig_covar", x),
}
}
}
impl FromStr for CovarFormat {
type Err = ParsingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().replace(" ", "").as_str() {
"sqrt" => Ok(CovarFormat::Sqrt),
"1sigma" | "sigma1" => Ok(CovarFormat::Sigma1),
"3sigma" | "sigma3" => Ok(CovarFormat::Sigma3),
_ => Err(ParsingError::CovarFormat),
}
}
}
pub fn parse_duration(duration: &str) -> Result<f64, ParsingError> {
let reg = Regex::new(r"^(\d+\.?\d*)\W*(\w+)$").unwrap();
match reg.captures(duration) {
Some(cap) => {
let mut time_s = cap[1].to_owned().parse::<f64>().unwrap();
match cap[2].to_owned().to_lowercase().as_str() {
"days" | "day" => time_s *= SECONDS_PER_DAY,
"hours" | "hour" => time_s *= SECONDS_PER_HOUR,
"min" | "mins" | "minute" | "minutes" => time_s *= SECONDS_PER_MINUTE,
"s" | "sec" | "secs" => time_s *= 1.0,
_ => {
return Err(ParsingError::Duration(format!(
"unknown duration unit in `{}`",
duration
)))
}
}
Ok(time_s)
}
None => Err(ParsingError::Duration(format!(
"Could not parse stopping condition: `{}`",
duration
))),
}
}