use crate::ldf::ldf_comment::skip_whitespace;
use nom::{
bytes::complete::{tag, take_until, take_while},
IResult,
};
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LdfSignalInitValue {
Scalar(u8),
Array(Vec<u8>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct LdfSignal {
pub name: String,
pub signal_size: u8,
pub init_value: LdfSignalInitValue,
pub published_by: String,
pub subscribed_by: Vec<String>,
}
pub fn parse_ldf_signals(s: &str) -> IResult<&str, Vec<LdfSignal>> {
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag("Signals")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag("{")(s)?;
let mut signals = Vec::new();
let mut remaining = s;
while !remaining.starts_with('}') {
let (s, _) = skip_whitespace(remaining)?;
let (s, signal_name) = take_while(|c: char| c.is_alphanumeric() || c == '_')(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag(":")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, signal_size) = take_while(|c: char| c.is_numeric())(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag(",")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, init_value) = take_while(|c: char| c.is_numeric())(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, _) = tag(",")(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, published_by) = take_while(|c: char| c.is_alphanumeric() || c == '_')(s)?;
let (s, _) = skip_whitespace(s)?;
let (s, symbol) = take_while(|c: char| c == ',' || c == ';')(s)?;
let mut subscribed_by = Vec::new();
let s = match symbol {
"," => {
let (s, subscribed_by_str) = take_until(";")(s)?;
subscribed_by = subscribed_by_str.split(',').map(|s| s.trim().to_string()).collect();
let (s, _) = tag(";")(s)?;
s
}
";" => {
s
}
_ => {
s
}
};
let (s, _) = skip_whitespace(s)?;
remaining = s;
let signal = LdfSignal {
name: signal_name.to_string(),
signal_size: signal_size.parse().unwrap(),
init_value: LdfSignalInitValue::Scalar(init_value.parse().unwrap()),
published_by: published_by.to_string(),
subscribed_by,
};
signals.push(signal);
}
let (s, _) = skip_whitespace(remaining)?;
let (s, _) = tag("}")(s)?;
Ok((s, signals))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_ldf_signals() {
let input = r#"
Signals {
Signal1: 10, 0, Master, Slave1 , Slave2 ;
Signal2: 10, 0, Master, Slave1 ;
Signal3: 10, 0, Slave1, Master ;
Signal4: 10, 0, Slave1, Master ;
Signal5: 2, 0, Slave1, Master ;
Signal6: 1, 0, Slave1, Master ;
}
"#;
let (_, signals) = parse_ldf_signals(input).unwrap();
assert_eq!(signals.len(), 6);
assert_eq!(signals[0].name, "Signal1");
assert_eq!(signals[0].signal_size, 10);
assert_eq!(signals[0].published_by, "Master");
assert_eq!(signals[0].subscribed_by, vec!["Slave1", "Slave2"]);
assert_eq!(signals[1].name, "Signal2");
}
}