Skip to main content

nmea_kit/ais/messages/
binary_multi_slot.rs

1//! AIS Type 26 — Multiple slot binary message with communication state.
2
3use crate::ais::armor::extract_u32;
4
5/// AIS Type 26 multiple-slot binary message.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct BinaryMultiSlot {
8    pub repeat_indicator: u8,
9    pub mmsi: u32,
10    pub destination_mmsi: Option<u32>,
11    /// `true` when an application identifier prefixes the binary data.
12    pub binary_data_flag: bool,
13    /// Raw application data, one bit per byte.
14    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}