use super::error::PodProductsError;
use serde::{Deserialize, Serialize};
use std::io::Write;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResidualRecord {
pub epoch_jd_tt: f64,
pub obs_type: String,
pub satellite: String,
pub residual_m: f64,
pub sigma_m: f64,
pub rejected: bool,
}
pub struct ResidualCsvWriter<W: Write> {
writer: W,
}
impl<W: Write> ResidualCsvWriter<W> {
pub fn new(mut writer: W) -> Result<Self, PodProductsError> {
writeln!(
writer,
"epoch_jd_tt,obs_type,satellite,residual_m,sigma_m,rejected"
)?;
writer.flush()?;
Ok(Self { writer })
}
pub fn write_record(&mut self, r: &ResidualRecord) -> Result<(), PodProductsError> {
writeln!(
self.writer,
"{:.9},{},{},{:.6},{:.6},{}",
r.epoch_jd_tt, r.obs_type, r.satellite, r.residual_m, r.sigma_m, r.rejected,
)?;
self.writer.flush()?;
Ok(())
}
pub fn flush(&mut self) -> Result<(), PodProductsError> {
self.writer.flush().map_err(PodProductsError::Io)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn streaming_writer_header() {
let mut buf = Vec::<u8>::new();
ResidualCsvWriter::new(&mut buf).unwrap();
let text = String::from_utf8(buf).unwrap();
assert_eq!(
text.trim(),
"epoch_jd_tt,obs_type,satellite,residual_m,sigma_m,rejected"
);
}
#[test]
fn streaming_writer_record_count() {
let mut buf = Vec::<u8>::new();
let mut w = ResidualCsvWriter::new(&mut buf).unwrap();
for i in 0..3 {
w.write_record(&ResidualRecord {
epoch_jd_tt: 2_451_545.0 + i as f64,
obs_type: "C1C".into(),
satellite: "G01".into(),
residual_m: 0.0,
sigma_m: 1.0,
rejected: false,
})
.unwrap();
}
let text = String::from_utf8(buf).unwrap();
assert_eq!(text.lines().count(), 4);
}
#[test]
fn streaming_writer_rejected_field() {
let mut buf = Vec::<u8>::new();
let mut w = ResidualCsvWriter::new(&mut buf).unwrap();
w.write_record(&ResidualRecord {
epoch_jd_tt: 2_451_545.0,
obs_type: "P2".into(),
satellite: "G03".into(),
residual_m: 10.0,
sigma_m: 1.0,
rejected: true,
})
.unwrap();
let text = String::from_utf8(buf).unwrap();
assert!(
text.contains(",true"),
"rejected=true must appear in output"
);
}
}