pub mod record;
pub use record::{ClockKey, ClockProfile, ClockProfileType, ClockType, Record};
use std::{
io::{BufWriter, Write},
str::FromStr,
};
use crate::{
fmt_rinex, parse_f64,
prelude::{FormattingError, TimeScale, Version, DOMES},
};
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct HeaderFields {
pub site: Option<String>,
pub domes: Option<DOMES>,
pub igs: Option<String>,
pub full_name: Option<String>,
pub ref_clock: Option<String>,
pub timescale: Option<TimeScale>,
pub work_clock: Vec<WorkClock>,
pub codes: Vec<ClockProfileType>,
}
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WorkClock {
pub name: String,
pub domes: Option<DOMES>,
pub constraint: Option<f64>,
}
impl WorkClock {
pub(crate) fn parse(version: Version, content: &str) -> Self {
const LIMIT: Version = Version { major: 3, minor: 4 };
if version < LIMIT {
let (name, rem) = content.split_at(4);
let (domes, rem) = rem.split_at(36);
let constraint = rem.split_at(20).0;
Self {
name: name.trim().to_string(),
domes: if let Ok(domes) = DOMES::from_str(domes.trim()) {
Some(domes)
} else {
None
},
constraint: if let Ok(value) = parse_f64(constraint.trim()) {
Some(value)
} else {
None
},
}
} else {
let (name, rem) = content.split_at(10);
let (domes, rem) = rem.split_at(10);
let constraint = rem.split_at(40).0;
Self {
name: name.trim().to_string(),
domes: if let Ok(domes) = DOMES::from_str(domes.trim()) {
Some(domes)
} else {
None
},
constraint: if let Ok(value) = parse_f64(constraint.trim()) {
Some(value)
} else {
None
},
}
}
}
}
impl HeaderFields {
pub(crate) fn format<W: Write>(&self, w: &mut BufWriter<W>) -> Result<(), FormattingError> {
write!(w, "{:6}", self.codes.len())?;
for (nth, code) in self.codes.iter().enumerate() {
write!(w, "{:6}", code,)?;
if nth % 9 == 8 {
writeln!(w, "# / TYPES OF DATA\n ")?;
}
}
if let Some(ts) = self.timescale {
writeln!(
w,
"{}",
fmt_rinex(&format!(" {:x}", ts), "TIME SYSTEM ID")
)?;
}
Ok(())
}
pub(crate) fn work_clock(&self, clk: WorkClock) -> Self {
let mut s = self.clone();
s.work_clock.push(clk);
s
}
pub(crate) fn timescale(&self, ts: TimeScale) -> Self {
let mut s = self.clone();
s.timescale = Some(ts);
s
}
pub(crate) fn site(&self, site: &str) -> Self {
let mut s = self.clone();
s.site = Some(site.to_string());
s
}
pub(crate) fn domes(&self, domes: DOMES) -> Self {
let mut s = self.clone();
s.domes = Some(domes);
s
}
pub(crate) fn igs(&self, igs: &str) -> Self {
let mut s = self.clone();
s.igs = Some(igs.to_string());
s
}
pub(crate) fn full_name(&self, name: &str) -> Self {
let mut s = self.clone();
s.full_name = Some(name.to_string());
s
}
pub(crate) fn refclock(&self, clk: &str) -> Self {
let mut s = self.clone();
s.ref_clock = Some(clk.to_string());
s
}
}