nmea_kit/ais/messages/
binary_multi_slot.rs1use crate::ais::armor::extract_u32;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct BinaryMultiSlot {
8 pub repeat_indicator: u8,
9 pub mmsi: u32,
10 pub destination_mmsi: Option<u32>,
11 pub binary_data_flag: bool,
13 pub data: Vec<u8>,
15 pub communication_state_selector: bool,
16 pub communication_state: u32,
17}
18
19impl BinaryMultiSlot {
20 pub(crate) fn decode(bits: &[u8]) -> Option<Self> {
21 if bits.len() < 64 {
22 return None;
23 }
24 let addressed = extract_u32(bits, 38, 1)? == 1;
25 let data_start = if addressed { 72 } else { 40 };
26 let data_end = bits.len().checked_sub(24)?;
27 let communication_state_start = bits.len().checked_sub(20)?;
28 if data_end < data_start {
29 return None;
30 }
31 Some(Self {
32 repeat_indicator: extract_u32(bits, 6, 2)? as u8,
33 mmsi: extract_u32(bits, 8, 30)?,
34 destination_mmsi: if addressed {
35 Some(extract_u32(bits, 40, 30)?)
36 } else {
37 None
38 },
39 binary_data_flag: extract_u32(bits, 39, 1)? == 1,
40 data: bits[data_start..data_end].to_vec(),
41 communication_state_selector: extract_u32(bits, communication_state_start, 1)? == 1,
42 communication_state: extract_u32(bits, communication_state_start + 1, 19)?,
43 })
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::ais::messages::test_helpers::set_bits;
51
52 #[test]
53 fn preserves_data_before_communication_state() {
54 let mut bits = vec![0; 72];
55 set_bits(&mut bits, 0, 6, 26);
56 set_bits(&mut bits, 38, 1, 0);
57 bits[40..48].copy_from_slice(&[1, 0, 1, 1, 0, 0, 1, 0]);
58 set_bits(&mut bits, 52, 1, 1);
59 set_bits(&mut bits, 53, 19, 0x5_4321);
60
61 let message = BinaryMultiSlot::decode(&bits).expect("decode");
62 assert_eq!(message.data, vec![1, 0, 1, 1, 0, 0, 1, 0]);
63 assert!(message.communication_state_selector);
64 assert_eq!(message.communication_state, 0x5_4321);
65 }
66}