use super::{Message, Signals};
use crate::{Error, MAX_NAME_SIZE, Parser, Result, Signal, compat};
impl Message {
pub(crate) fn parse(parser: &mut Parser, signals: &[Signal]) -> Result<Self> {
let line = parser.line();
parser
.expect(crate::BO_.as_bytes())
.map_err(|_| Error::expected_at("Expected BO_ keyword", line))?;
let _ = parser.skip_whitespace();
let id = parser.parse_u32_with_error(|| Error::message(Error::MESSAGE_INVALID_ID))?;
let line = parser.line();
parser
.skip_whitespace()
.map_err(|_| Error::expected_at("Expected space after message ID", line))?;
let name =
parser.parse_identifier_with_error(|| Error::message(Error::MESSAGE_NAME_EMPTY))?;
let _ = parser.skip_whitespace();
parser.expect_with_msg(b":", "Expected ':' after message name")?;
let _ = parser.skip_whitespace();
let dlc = parser.parse_u8_with_error(|| Error::message(Error::MESSAGE_INVALID_DLC))?;
let line = parser.line();
parser
.skip_whitespace()
.map_err(|_| Error::expected_at("Expected space after DLC", line))?;
let sender =
parser.parse_identifier_with_error(|| Error::message(Error::MESSAGE_SENDER_EMPTY))?;
parser.skip_newlines_and_spaces();
if !parser.is_empty() {
return Err(parser.err_expected("Unexpected content after message sender"));
}
Message::validate(id, name, dlc, sender, signals).map_err(|e| {
crate::error::map_val_error_with_line(
e,
|msg| parser.err_message(msg),
|| parser.err_message(Error::MESSAGE_ERROR_PREFIX),
)
})?;
let name_str: compat::String<{ MAX_NAME_SIZE }> = compat::validate_name(name)?;
let sender_str: compat::String<{ MAX_NAME_SIZE }> = compat::validate_name(sender)?;
let signals_collection = Signals::from_slice(signals);
Ok(Message::new(
id,
name_str,
dlc,
sender_str,
signals_collection,
None,
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Error, Signal};
#[test]
fn test_message_parse_valid() {
let data = b"BO_ 256 EngineData : 8 ECM";
let mut parser = Parser::new(data).unwrap();
let signals: &[Signal] = &[];
let message = Message::parse(&mut parser, signals).unwrap();
assert_eq!(message.id(), 256);
assert_eq!(message.name(), "EngineData");
assert_eq!(message.dlc(), 8);
assert_eq!(message.sender(), "ECM");
assert_eq!(message.signals().len(), 0);
}
#[test]
fn test_message_parse_invalid_id() {
let data = b"BO_ invalid EngineData : 8 ECM";
let mut parser = Parser::new(data).unwrap();
let signals: &[Signal] = &[];
let result = Message::parse(&mut parser, signals);
assert!(result.is_err());
match result.unwrap_err() {
Error::Message { line, .. } => {
assert_eq!(line, Some(1));
}
_ => panic!("Expected Error::Message"),
}
}
#[test]
fn test_message_parse_empty_name() {
let data = b"BO_ 256 : 8 ECM";
let mut parser = Parser::new(data).unwrap();
let signals: &[Signal] = &[];
let result = Message::parse(&mut parser, signals);
assert!(result.is_err());
match result.unwrap_err() {
Error::Message { line, .. } => {
assert_eq!(line, Some(1));
}
_ => panic!("Expected Error::Message"),
}
}
#[test]
fn test_message_parse_invalid_dlc() {
let data = b"BO_ 256 EngineData : invalid ECM";
let mut parser = Parser::new(data).unwrap();
let signals: &[Signal] = &[];
let result = Message::parse(&mut parser, signals);
assert!(result.is_err());
match result.unwrap_err() {
Error::Message { line, .. } => {
assert_eq!(line, Some(1));
}
_ => panic!("Expected Error::Message"),
}
}
#[test]
fn test_message_parse_empty_sender() {
let data = b"BO_ 256 EngineData : 8 ";
let mut parser = Parser::new(data).unwrap();
let signals: &[Signal] = &[];
let result = Message::parse(&mut parser, signals);
assert!(result.is_err());
match result.unwrap_err() {
Error::Message { line, .. } => {
assert_eq!(line, Some(1));
}
_ => panic!("Expected Error::Message"),
}
}
#[test]
fn test_message_parse_with_signals() {
let data = b"BO_ 256 EngineData : 8 ECM";
let mut parser = Parser::new(data).unwrap();
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@1+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Temp : 16|8@1- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
)
.unwrap();
let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
assert_eq!(message.id(), 256);
assert_eq!(message.name(), "EngineData");
assert_eq!(message.dlc(), 8);
assert_eq!(message.sender(), "ECM");
assert_eq!(message.signals().len(), 2);
}
}