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 format_timestamp(t: f64) -> String {
let mut s = format!("{t:.6}");
if !s.starts_with('-') {
s = format!(" {s}");
}
while s.len() < 9 {
s = format!(" {s}");
}
s
}
pub fn write_asc_frames<'a, W: Write>(
frames: &[CanFrame<'a>],
start_time_ns: Option<i64>,
out: &mut W,
) -> Result<()> {
writeln!(out, "{}", format_date_header(start_time_ns))?;
writeln!(out, "base hex timestamps absolute")?;
writeln!(out, "no internal events logged")?;
for frame in frames {
let t_str = format_timestamp(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)
};
let dir = "Rx";
let dlc = frame.data.len();
let data_str = frame
.data
.iter()
.map(|b| format!("{b:02X}"))
.collect::<Vec<_>>()
.join(" ");
writeln!(
out,
"{t_str} {bus} {id_str:<15} {dir:<4} d {dlc:x} {data_str}"
)?;
}
Ok(())
}