use uart_proto_detector::{
GenericParser, PacketLengthStrategy, ParserConfig, ParserError, BUFFER_SIZE,
};
fn feed(parser: &mut GenericParser, bytes: &[u8]) -> Option<Vec<u8>> {
for &b in bytes {
match parser.parse_byte(b) {
Ok(Some(packet)) => return Some(packet.to_vec()),
Ok(None) => {}
Err(e) => panic!("Erreur inattendue : {:?}", e),
}
}
None
}
#[test]
fn fixed_length_happy_path() {
let config = ParserConfig {
header: &[0xAA, 0x55],
length_strategy: PacketLengthStrategy::Fixed(6),
};
let mut parser = GenericParser::new(config);
let stream: &[u8] = &[0xAA, 0x55, 0x01, 0x02, 0x03, 0x04];
let result = feed(&mut parser, stream);
assert_eq!(result, Some(vec![0xAA, 0x55, 0x01, 0x02, 0x03, 0x04]));
}
#[test]
fn fixed_length_garbage_before_header() {
let config = ParserConfig {
header: &[0xAA, 0x55],
length_strategy: PacketLengthStrategy::Fixed(4),
};
let mut parser = GenericParser::new(config);
let stream: &[u8] = &[0x00, 0xFF, 0xDE, 0xAA, 0x55, 0xBE, 0xEF];
let result = feed(&mut parser, stream);
assert_eq!(result, Some(vec![0xAA, 0x55, 0xBE, 0xEF]));
}
#[test]
fn fixed_length_multiple_packets() {
let config = ParserConfig {
header: &[0xFF],
length_strategy: PacketLengthStrategy::Fixed(3),
};
let mut parser = GenericParser::new(config);
let mut packets: Vec<Vec<u8>> = Vec::new();
let stream: &[u8] = &[0xFF, 0x01, 0x02, 0xFF, 0x03, 0x04];
for &b in stream {
if let Ok(Some(p)) = parser.parse_byte(b) {
packets.push(p.to_vec());
}
}
assert_eq!(packets.len(), 2);
assert_eq!(packets[0], vec![0xFF, 0x01, 0x02]);
assert_eq!(packets[1], vec![0xFF, 0x03, 0x04]);
}
#[test]
fn length_byte_happy_path() {
let config = ParserConfig {
header: &[0xAA, 0x55],
length_strategy: PacketLengthStrategy::LengthByte { index: 2, offset: 3 },
};
let mut parser = GenericParser::new(config);
let stream: &[u8] = &[0xAA, 0x55, 0x03, 0x10, 0x20, 0xCK];
let stream: &[u8] = &[0xAA, 0x55, 0x03, 0x10, 0x20, 0x30];
let result = feed(&mut parser, stream);
assert_eq!(result, Some(vec![0xAA, 0x55, 0x03, 0x10, 0x20, 0x30]));
}
#[test]
fn length_byte_payload_zero() {
let config = ParserConfig {
header: &[0xBB],
length_strategy: PacketLengthStrategy::LengthByte { index: 1, offset: 2 },
};
let mut parser = GenericParser::new(config);
let stream: &[u8] = &[0xBB, 0x00];
let result = feed(&mut parser, stream);
assert_eq!(result, Some(vec![0xBB, 0x00]));
}
#[test]
fn error_packet_too_large_fixed() {
let config = ParserConfig {
header: &[0xAA],
length_strategy: PacketLengthStrategy::Fixed(BUFFER_SIZE + 1),
};
let mut parser = GenericParser::new(config);
assert_eq!(parser.parse_byte(0xAA), Ok(None));
let result = parser.parse_byte(0x01);
assert_eq!(result, Err(ParserError::PacketTooLarge(BUFFER_SIZE + 1)));
}
#[test]
fn error_packet_too_large_length_byte() {
let config = ParserConfig {
header: &[0xCC],
length_strategy: PacketLengthStrategy::LengthByte { index: 1, offset: 2 },
};
let mut parser = GenericParser::new(config);
parser.parse_byte(0xCC).unwrap(); let result = parser.parse_byte(0xFF); assert_eq!(result, Err(ParserError::PacketTooLarge(257)));
}
#[test]
fn error_invalid_length_byte_index() {
let config = ParserConfig {
header: &[0xDD],
length_strategy: PacketLengthStrategy::LengthByte {
index: BUFFER_SIZE, offset: 0,
},
};
let mut parser = GenericParser::new(config);
parser.parse_byte(0xDD).unwrap();
let mut got_error = false;
for i in 0u8..10 {
match parser.parse_byte(i) {
Err(ParserError::InvalidLengthByteIndex) => {
got_error = true;
break;
}
Err(_) | Ok(_) => {}
}
}
assert!(got_error, "InvalidLengthByteIndex aurait dû être retourné");
}
#[test]
fn error_buffer_overflow_recovery() {
let config = ParserConfig {
header: &[0xEE],
length_strategy: PacketLengthStrategy::Fixed(200),
};
let mut parser = GenericParser::new(config);
parser.parse_byte(0xEE).unwrap();
let result = parser.parse_byte(0x01);
assert_eq!(result, Err(ParserError::PacketTooLarge(200)));
assert_eq!(parser.bytes_accumulated(), 0);
assert_eq!(parser.expected_length(), None);
}
#[test]
fn introspection_bytes_accumulated() {
let config = ParserConfig {
header: &[0x01, 0x02],
length_strategy: PacketLengthStrategy::Fixed(5),
};
let mut parser = GenericParser::new(config);
assert_eq!(parser.bytes_accumulated(), 0);
parser.parse_byte(0x01).unwrap();
assert_eq!(parser.bytes_accumulated(), 1);
parser.parse_byte(0x02).unwrap();
assert_eq!(parser.bytes_accumulated(), 2);
}
#[test]
fn introspection_expected_length_fixed() {
let config = ParserConfig {
header: &[0xAB],
length_strategy: PacketLengthStrategy::Fixed(10),
};
let mut parser = GenericParser::new(config);
assert_eq!(parser.expected_length(), None);
parser.parse_byte(0xAB).unwrap(); parser.parse_byte(0x00).unwrap(); assert_eq!(parser.expected_length(), Some(10));
}