use regex::Regex;
use std::{error::Error, fmt::Display, fs::OpenOptions, io::Write};
#[derive(Debug, Clone)]
pub struct UnparsableFileError {
inner: String,
}
impl Error for UnparsableFileError {}
impl Display for UnparsableFileError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Cannot parse file, because {}", self.inner)
}
}
impl From<csv::Error> for UnparsableFileError {
fn from(value: csv::Error) -> Self {
UnparsableFileError {
inner: value.to_string(),
}
}
}
pub fn run_lfp(source: &str) -> Result<String, Box<dyn std::error::Error>> {
let re = Regex::new(r"(\d){3}").unwrap();
let mut rdr = csv::ReaderBuilder::new()
.delimiter(b',')
.flexible(true)
.from_path(source)?;
let headers_raw = rdr.records().next().unwrap()?;
let headers = headers_raw
.into_iter()
.map(|col| match re.find(col) {
Some(mtch) => mtch.as_str(),
None => "",
})
.collect::<Vec<_>>();
let mut body: Vec<Vec<String>> = vec![];
for record in rdr.records().skip(8) {
let record_vec = record?.into_iter().map(|s| s.to_owned()).collect();
body.push(record_vec)
}
let output_filename = format!("{}.ascii", source.split_once(".").unwrap_or(("file", "")).0);
let headlines = headers.len() - 1; let filename = write_to_file(headers, body, headlines, &output_filename).unwrap();
Ok(filename)
}
pub fn run_das6(
source: &str,
sync_delay: f32,
ns_per_chn: f32,
output_filename: String,
) -> Result<String, UnparsableFileError> {
let mut rdr = csv::ReaderBuilder::new()
.delimiter(b'\t')
.from_path(source)
.expect("Problema leyendo archivo");
let re = Regex::new(r"(\d){3}").unwrap();
let mut body: Vec<Vec<_>> = vec![];
for (n, record) in rdr.records().enumerate() {
let mut line = record?
.into_iter()
.map(|recn| recn.to_string())
.collect::<Vec<String>>();
line.insert(
0,
format!("{}", ((n as f32 - sync_delay) * ns_per_chn) as i32),
);
line.remove(1); body.push(line.clone()); }
let mut headers = rdr
.headers()?
.into_iter()
.filter_map(|rec| match re.captures(rec) {
None => None,
Some(caps) => caps.get(0).map_or(Some("0"), |m| Some(m.as_str())),
})
.collect::<Vec<&str>>();
headers.push("");
let headlines = headers.len();
let filename = write_to_file(headers, body, headlines, &output_filename).unwrap();
Ok(filename)
}
fn write_to_file(
headers: Vec<&str>,
body: Vec<Vec<String>>,
line_number: usize,
output_filename: &str,
) -> Result<String, Box<dyn Error>> {
let filename = output_filename;
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open(filename)?;
writeln!(file, "{filename}")?;
writeln!(file, "Eduardo Gonik")?;
writeln!(file, "wavelength explicit")?;
let ii = format!("intervalnr {}", (line_number - 1));
writeln!(file, "{ii}")?;
file.flush()?;
let file2 = OpenOptions::new().append(true).open(filename)?;
let mut writer = csv::WriterBuilder::new()
.delimiter(b'\t')
.from_writer(file2);
writer.write_record(&headers).unwrap();
body.into_iter()
.for_each(|v| writer.write_record(&v).unwrap());
writer.flush()?;
Ok(filename.into())
}