use crate::ldf::ldf_comment::skip_whitespace;
use nom::{
bytes::complete::{tag, take_while},
IResult,
};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LdfDiagnosticFrame {
pub frame_name: String,
pub frame_id: u8,
pub signals: Vec<LdfDiagnosticFrameSignal>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LdfDiagnosticFrameSignal {
pub signal_name: String,
pub start_bit: u8,
}
pub fn parse_ldf_diagnostic_frames(s: &str) -> IResult<&str, Vec<LdfDiagnosticFrame>> {
let (s, _) = skip_whitespace(s)?;
if !s.starts_with("Diagnostic_frames") {
return Ok((s, Vec::new()));
}
let (s, _) = tag("Diagnostic_frames")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag("{")(s)?;
let (s, _) = skip_whitespace(s)?;
let mut diagnostic_frames = Vec::new();
let mut remaining = s;
while !remaining.starts_with('}') {
let (s, frame_name) = take_while(|c: char| c != ':' && c != '{')(remaining)?;
let (s, _) = tag(":")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag("0x")(s)?;
let (s, frame_id) = take_while(|c: char| c != ' ' && c != '{')(s)?;
let frame_id = u8::from_str_radix(frame_id, 16).unwrap();
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag("{")(s)?;
let (s, _) = skip_whitespace(s)?;
let mut signals = Vec::new();
remaining = s;
while !remaining.starts_with('}') {
let (s, signal_name) = take_while(|c: char| c != ',' && c != ';')(remaining)?;
let (s, _) = tag(",")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, start_bit) = take_while(|c: char| c.is_numeric())(s)?;
let start_bit = u8::from_str_radix(start_bit, 10).unwrap();
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag(";")(s)?;
signals.push(LdfDiagnosticFrameSignal {
signal_name: signal_name.to_string(),
start_bit,
});
let (s, _) = skip_whitespace(s)?;
remaining = s;
}
let (s, _) = tag("}")(remaining)?;
let (s, _) = skip_whitespace(s)?;
diagnostic_frames.push(LdfDiagnosticFrame {
frame_name: frame_name.to_string(),
frame_id,
signals,
});
remaining = s;
}
let (remaining, _) = tag("}")(remaining)?;
Ok((remaining, diagnostic_frames))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_ldf_diagnostic_frames() {
let input = r#"
Diagnostic_frames {
MasterReq: 0x3C {
MasterReqB0, 0 ;
MasterReqB1, 8 ;
MasterReqB2, 16 ;
MasterReqB3, 24 ;
MasterReqB4, 32 ;
MasterReqB5, 40 ;
MasterReqB6, 48 ;
MasterReqB7, 56 ;
}
SlaveResp: 0x3D {
SlaveRespB0, 0 ;
SlaveRespB1, 8 ;
SlaveRespB2, 16 ;
SlaveRespB3, 24 ;
SlaveRespB4, 32 ;
SlaveRespB5, 40 ;
SlaveRespB6, 48 ;
SlaveRespB7, 56 ;
}
}
"#;
let (_, diagnostic_frames) = parse_ldf_diagnostic_frames(input).unwrap();
assert_eq!(diagnostic_frames.len(), 2);
assert_eq!(diagnostic_frames[0].frame_name, "MasterReq");
assert_eq!(diagnostic_frames[0].frame_id, 0x3C);
assert_eq!(diagnostic_frames[0].signals.len(), 8);
assert_eq!(diagnostic_frames[0].signals[0].signal_name, "MasterReqB0");
assert_eq!(diagnostic_frames[0].signals[0].start_bit, 0);
assert_eq!(diagnostic_frames[0].signals[7].signal_name, "MasterReqB7");
assert_eq!(diagnostic_frames[0].signals[7].start_bit, 56);
assert_eq!(diagnostic_frames[1].frame_name, "SlaveResp");
assert_eq!(diagnostic_frames[1].frame_id, 0x3D);
assert_eq!(diagnostic_frames[1].signals.len(), 8);
assert_eq!(diagnostic_frames[1].signals[0].signal_name, "SlaveRespB0");
assert_eq!(diagnostic_frames[1].signals[0].start_bit, 0);
assert_eq!(diagnostic_frames[1].signals[7].signal_name, "SlaveRespB7");
assert_eq!(diagnostic_frames[1].signals[7].start_bit, 56);
}
}