use bebytes::BeBytes;
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct MarkerTest {
header: u8,
#[UntilMarker(0x00)]
null_terminated: Vec<u8>,
#[AfterMarker(0x00)]
remainder: Vec<u8>,
}
#[test]
fn test_null_marker() {
let msg = MarkerTest {
header: 0x42,
null_terminated: vec![0x01, 0x02, 0x03],
remainder: vec![0xAA, 0xBB],
};
let bytes = msg.to_be_bytes();
assert_eq!(bytes[0], 0x42); assert_eq!(bytes[1], 0x01); assert_eq!(bytes[2], 0x02);
assert_eq!(bytes[3], 0x03);
assert_eq!(bytes[4], 0x00); assert_eq!(bytes[5], 0x00); assert_eq!(bytes[6], 0xAA);
assert_eq!(bytes[7], 0xBB);
let (parsed, consumed) = MarkerTest::try_from_be_bytes(&bytes).unwrap();
assert_eq!(consumed, 8);
assert_eq!(parsed, msg);
}
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct MultipleMarkers {
#[UntilMarker(0x7F)]
first: Vec<u8>,
#[UntilMarker(0xFF)]
second: Vec<u8>,
final_byte: u8,
}
#[test]
fn test_multiple_until_markers() {
let msg = MultipleMarkers {
first: vec![0x10, 0x20],
second: vec![0x30, 0x40, 0x50],
final_byte: 0x99,
};
let bytes = msg.to_be_bytes();
assert_eq!(bytes.len(), 8);
let (parsed, consumed) = MultipleMarkers::try_from_be_bytes(&bytes).unwrap();
assert_eq!(consumed, bytes.len());
assert_eq!(parsed.first, vec![0x10, 0x20]);
assert_eq!(parsed.second, vec![0x30, 0x40, 0x50]);
assert_eq!(parsed.final_byte, 0x99);
}
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct MarkerInData {
#[UntilMarker(0xAB)]
data: Vec<u8>,
tail: u8,
}
#[test]
fn test_marker_byte_in_data() {
let bytes = vec![0x11, 0x22, 0xAB, 0x33];
let (parsed, consumed) = MarkerInData::try_from_be_bytes(&bytes).unwrap();
assert_eq!(consumed, 4);
assert_eq!(parsed.data, vec![0x11, 0x22]); assert_eq!(parsed.tail, 0x33);
}
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct EmptyMarkerFields {
prefix: u8,
#[UntilMarker(0xDD)]
empty_until: Vec<u8>,
middle: u8,
#[AfterMarker(0xEE)]
empty_after: Vec<u8>,
}
#[test]
fn test_immediate_marker() {
let bytes = vec![
0x01, 0xDD, 0x02, 0xEE, ];
let (parsed, consumed) = EmptyMarkerFields::try_from_be_bytes(&bytes).unwrap();
assert_eq!(consumed, 4);
assert_eq!(parsed.prefix, 0x01);
assert_eq!(parsed.empty_until, Vec::<u8>::new());
assert_eq!(parsed.middle, 0x02);
assert_eq!(parsed.empty_after, Vec::<u8>::new());
}
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct AfterMarkerConsumesAll {
header: u16,
#[AfterMarker(0xFE)]
all_remaining: Vec<u8>,
}
#[test]
fn test_after_marker_consumes_remaining() {
let msg = AfterMarkerConsumesAll {
header: 0x1234,
all_remaining: vec![0x01, 0x02, 0x03, 0x04, 0x05],
};
let bytes = msg.to_be_bytes();
assert_eq!(bytes[0], 0x12); assert_eq!(bytes[1], 0x34); assert_eq!(bytes[2], 0xFE); assert_eq!(bytes[3], 0x01); assert_eq!(bytes[7], 0x05);
let (parsed, consumed) = AfterMarkerConsumesAll::try_from_be_bytes(&bytes).unwrap();
assert_eq!(consumed, 8);
assert_eq!(parsed.header, 0x1234);
assert_eq!(parsed.all_remaining, vec![0x01, 0x02, 0x03, 0x04, 0x05]);
}
#[test]
fn test_marker_round_trip_consistency() {
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct ComplexMarker {
version: u8,
flags: u8,
#[UntilMarker(0xFD)]
options: Vec<u8>,
#[UntilMarker(0xFE)]
extensions: Vec<u8>,
#[AfterMarker(0xFF)]
payload: Vec<u8>,
}
let original = ComplexMarker {
version: 1,
flags: 0b10101010,
options: vec![0x11, 0x22, 0x33],
extensions: vec![0x44, 0x55],
payload: vec![0xAA, 0xBB, 0xCC, 0xDD],
};
let bytes = original.to_be_bytes();
let (parsed, _) = ComplexMarker::try_from_be_bytes(&bytes).unwrap();
assert_eq!(parsed, original);
let bytes2 = parsed.to_be_bytes();
assert_eq!(bytes, bytes2);
}
#[test]
fn test_no_marker_in_stream() {
#[derive(Debug, Clone, PartialEq, BeBytes)]
struct RequiresMarker {
#[UntilMarker(0xCC)]
data: Vec<u8>,
after: u8,
}
let bytes = vec![0x11, 0x22, 0x33, 0x44, 0x55];
let result = RequiresMarker::try_from_be_bytes(&bytes);
match result {
Ok((parsed, consumed)) => {
assert_eq!(consumed, 5);
assert_eq!(parsed.data, vec![0x11, 0x22, 0x33, 0x44, 0x55]);
}
Err(_) => {
}
}
}