use std::io::Write;
use crate::bus::CanFrame;
use crate::error::Result;
use crate::Mf4File;
pub fn write_asc<W: Write>(file: &Mf4File, out: &mut W) -> Result<()> {
let mut groups_frames = Vec::new();
for group in file.can_frame_groups() {
groups_frames.push(file.can_frames(group)?);
}
let mut all_frames = Vec::new();
for frames in &groups_frames {
for frame in frames.iter() {
all_frames.push(frame);
}
}
all_frames.sort_by(|a, b| a.timestamp.total_cmp(&b.timestamp));
let start_time_ns = file.start_time().timestamp_ns;
write_asc_frames(&all_frames, Some(start_time_ns), out)
}
fn format_date_header(start_time_ns: Option<i64>) -> String {
let Some(ns) = start_time_ns else {
return "date Thu Jan 01 12:00:00.000000 AM 1970".to_string();
};
if ns <= 0 {
return "date Thu Jan 01 12:00:00.000000 AM 1970".to_string();
}
let secs = ns / 1_000_000_000;
let subsec_ns = (ns % 1_000_000_000) as u32;
let dt = chrono::DateTime::from_timestamp(secs, subsec_ns);
match dt {
Some(d) => format!("date {}", d.format("%a %b %d %I:%M:%S.%6f %p %Y")),
None => "date Thu Jan 01 12:00:00.000000 AM 1970".to_string(),
}
}
fn write_timestamp(buf: &mut String, t: f64) {
use std::fmt::Write as _;
buf.clear();
write!(buf, "{t:.6}").expect("writing to a String cannot fail");
if !buf.starts_with('-') {
buf.insert(0, ' ');
}
while buf.len() < 9 {
buf.insert(0, ' ');
}
}
pub fn write_asc_frames<'a, W: Write>(
frames: &[CanFrame<'a>],
start_time_ns: Option<i64>,
out: &mut W,
) -> Result<()> {
use std::fmt::Write as _;
writeln!(out, "{}", format_date_header(start_time_ns))?;
writeln!(out, "base hex timestamps absolute")?;
writeln!(out, "no internal events logged")?;
let mut row = String::with_capacity(96);
for frame in frames {
row.clear();
write_timestamp(&mut row, frame.timestamp);
let bus = if frame.bus_channel == 0 {
1
} else {
frame.bus_channel
};
let is_ext = frame.extended.unwrap_or(frame.id > 0x7FF);
let id_str = if is_ext {
format!("{:x}x", frame.id)
} else {
format!("{:x}", frame.id)
};
write!(row, " {bus} {id_str:<15} Rx d {:x} ", frame.data.len())
.expect("writing to a String cannot fail");
for (i, byte) in frame.data.iter().enumerate() {
if i > 0 {
row.push(' ');
}
write!(row, "{byte:02X}").expect("writing to a String cannot fail");
}
row.push('\n');
out.write_all(row.as_bytes())?;
}
Ok(())
}