use std::collections::HashMap;
use crate::data_types::Mjd;
use crate::error::PsruError;
use crate::parse_tools::parse_f64;
#[derive(Debug, PartialEq)]
pub struct TOAInfo {
pub is_bad: bool,
pub file: String,
pub frequency: f64,
pub mjd: Mjd,
pub mjd_error: f64,
pub site_id: String,
pub comment: String,
pub flags: HashMap<String, Flag>,
}
impl TOAInfo {
pub fn from_line_tempo2(line: &str) -> Result<Self, PsruError> {
let parts = line.split_ascii_whitespace().collect::<Vec<_>>();
Self::parse_tempo2(&parts)
}
pub(crate) fn parse_tempo2(parts: &[&str]) -> Result<Self, PsruError> {
let is_bad = parts[0] == "c" || parts[0] == "C";
let (mut comments, mut values): (Vec<&str>, Vec<&str>) = parts
.iter()
.partition(|w| w.starts_with('#') && w.len() > 1);
if let Some(pos) = values.iter().position(|w| *w == "#") {
values.split_off(pos)[1..]
.iter()
.for_each(|c| comments.push(c));
}
let comment = comments.join(" -- ");
let mut values = values.into_iter();
if is_bad {
_ = values.next();
}
let file = values
.next()
.ok_or(PsruError::TimUnexpectedEOL(None))?
.to_string();
let freq_text =
values.next().ok_or(PsruError::TimUnexpectedEOL(None))?;
let frequency = parse_f64(freq_text)?;
let mjd_text =
values.next().ok_or(PsruError::TimUnexpectedEOL(None))?;
let mjd = mjd_text.parse::<Mjd>()?;
let err_text =
values.next().ok_or(PsruError::TimUnexpectedEOL(None))?;
let error = parse_f64(err_text)?;
let site_id = values
.next()
.ok_or(PsruError::TimUnexpectedEOL(None))?
.to_string();
let remains = values.collect::<Vec<_>>();
let chunks = remains.chunks_exact(2);
if !chunks.remainder().is_empty() {
return Err(PsruError::TimUnvaluedFlag(
None,
chunks.remainder()[0].to_string(),
));
}
let flags = chunks
.map(|s| parse_flag(s[0], s[1]))
.collect::<HashMap<String, Flag>>();
Ok(Self {
is_bad,
file,
frequency,
mjd,
mjd_error: error,
site_id,
comment,
flags,
})
}
pub(crate) fn parse_parkes(line: &str) -> Result<Self, PsruError> {
if !line.is_ascii() {
return Err(PsruError::TimNotAscii(None));
}
if &line[0..1] != " " {
return Err(PsruError::TimParkesMissingBlank(None));
}
if &line[41..42] != "." {
return Err(PsruError::TimParkesMissingPeriod(None));
}
todo!()
}
}
fn parse_flag(key: &str, value: &str) -> (String, Flag) {
let key = key
.strip_prefix('-')
.map_or_else(|| key.to_string(), str::to_string);
let value = parse_f64(value)
.map_or_else(|_| Flag::String(value.to_string()), Flag::Double);
(key, value)
}
#[derive(Debug, PartialEq)]
pub enum Flag {
Double(f64),
String(String),
}