use std::num::ParseIntError;
use mt_raw::MtRaw;
use mt_structured::MtStructured;
use rss::Rss;
use thiserror::Error;
pub mod mt_raw;
pub mod mt_structured;
pub mod rss;
#[derive(Error, Clone, Debug, PartialEq)]
pub enum ParseError {
#[error("failed to parse number")]
ParseIntError(#[from] ParseIntError),
#[error("invalid message size (expected {expected:?}, found {found:?})")]
SizeNotMatch { expected: usize, found: usize },
#[error("invalid sentence, not parsable")]
Invalid(),
}
#[derive(Clone, Debug, PartialEq)]
pub enum ParsedMessage {
Rss(Rss),
MtStructured(MtStructured),
MtRaw(MtRaw),
Invalid(),
}
pub fn parse(message: &str) -> Result<ParsedMessage, ParseError> {
let parsed = match message.trim() {
msg if Rss::is_rss(msg) => ParsedMessage::Rss(Rss::parse(msg)?),
msg if MtStructured::is_mt(msg) => ParsedMessage::MtStructured(MtStructured::parse(msg)?),
msg if MtRaw::is_mt(msg) => ParsedMessage::MtRaw(MtRaw::parse(msg)?),
_ => ParsedMessage::Invalid(),
};
Ok(parsed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mt_structured() {
assert!(parse("MT1001000AL400C592753572B323433212S1723756E4706").is_ok());
assert!(parse("MT1001000AL400C592753572B323433212S1723756E4706").is_ok());
}
#[test]
fn mt_raw() {
assert!(parse("MT6001001FFFE2FA00E0000CBAB959DB0903788C71B79F84B").is_ok());
assert!(parse("MT6001001FFFE2FA0062C93A9AB959E55EE7788C71B791131").is_ok());
}
#[test]
fn invalid_mt() {
let invalid_samples = vec![
"MT2001000AL400C592753572B323433212S1723756E4706",
"MT3001000AL400C592753572B323433212S1723756E4706",
"MT4001000AL400C592753572B323433212S1723756E4706",
"MT5001000AL400C592753572B323433212S1723756E4706",
"MT8001000AL400C592753572B323433212S1723756E4706",
"MT9001000AL400C592753572B323433212S1723756E4706",
"MT0001000AL400C592753572B323433212S1723756E4706",
];
for s in invalid_samples {
assert_eq!(parse(s).unwrap(), ParsedMessage::Invalid());
}
assert!(parse("MT6001001FFFE2FA00E0000CBAB959DB0903788C71B").is_err());
assert!(parse("MT1001000AL400C592753572B323433212S172375").is_err());
assert!(parse("MT1001aaaAL400C592753572B323433212S1723756E4706").is_err());
assert!(parse("MT6001aaaFFFE2FA00E0000CBAB959DB0903788C71B79F84B").is_err());
assert!(parse("MT1001000AL400C592753572B323aa3212S1723756E4706").is_err());
assert!(parse("MT1001000AL400C592753572B32343bb12S1723756E4706").is_err());
assert!(parse("MT1001000AL400C592753572B3234332ccS1723756E4706").is_err());
assert!(parse("MT1001000AL400C592753572B323433212Saaa3756E4706").is_err());
assert!(parse("MT1001000AL400C592753572B323433212S172bb56E4706").is_err());
assert!(parse("MT1001000AL400C592753572B323433212S17237ccE4706").is_err());
assert!(parse("MT1001000AL400C592753572B323433212S1723756EZZZZ").is_err());
assert!(parse("MT6001001FFFE2FA00E0000CBAB959DB0903788C71B79ZZZZ").is_err());
}
#[test]
fn rss() {
assert!(parse("SS,A,123\n").is_ok());
assert!(parse("SS,1,123\n").is_ok());
}
#[test]
fn invalid_rss() {
assert!(parse("SS,1,666\n").is_err()); assert!(parse("SS,1,12367\n").is_err()); assert!(parse("SS,2,123\n").is_err()); assert!(parse("SS,A,1234\n").is_err()); assert!(parse("SS,X,123\n").is_err()); }
#[test]
fn hardcoded_checksum() {
assert_eq!(
MtRaw::calculate_checksum("FFFE2FA00E0000CBAB959DB0903788C71B79".as_bytes()),
0xf84b
);
}
#[test]
fn mt_raw_checksum() {
if let Ok(ParsedMessage::MtRaw(v)) =
parse("MT6001001FFFE2FA00E0000CBAB959DB0903788C71B79F84B")
{
assert_eq!(MtRaw::calculate_checksum(&v.data), v.checksum);
}
}
}