use crate::bits::{BitReader, BitWriter};
use crate::error::{BitError, MessageError};
use crate::message::common::Mmsi;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageRequest {
pub message_type: u8,
pub slot_offset: u16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SecondStation {
pub mmsi: Mmsi,
pub request: MessageRequest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Interrogation {
pub repeat_indicator: u8,
pub mmsi: Mmsi,
pub station_1_mmsi: Mmsi,
pub station_1_request_1: MessageRequest,
pub station_1_request_2: Option<MessageRequest>,
pub station_2: Option<SecondStation>,
}
impl Interrogation {
pub(crate) fn decode(r: &mut BitReader<'_>) -> Result<Self, MessageError> {
let repeat_indicator = r.read_u8(2)?;
let mmsi = Mmsi::from_raw(r.read_u32(30)?);
r.skip(2)?; let station_1_mmsi = Mmsi::from_raw(r.read_u32(30)?);
let station_1_request_1 = decode_request(r)?;
if r.remaining_bits() >= 2 {
r.skip(2)?; }
let station_1_request_2 = if r.remaining_bits() >= 18 {
Some(decode_request(r)?)
} else {
None
};
if r.remaining_bits() >= 2 {
r.skip(2)?; }
let station_2 = if r.remaining_bits() >= 48 {
let station_mmsi = Mmsi::from_raw(r.read_u32(30)?);
let request = decode_request(r)?;
Some(SecondStation {
mmsi: station_mmsi,
request,
})
} else {
None
};
if r.remaining_bits() >= 2 {
r.skip(2)?; }
Ok(Self {
repeat_indicator,
mmsi,
station_1_mmsi,
station_1_request_1,
station_1_request_2,
station_2,
})
}
pub(crate) fn encode(&self, w: &mut BitWriter<'_>) -> Result<(), BitError> {
w.write_bits(15, 6)?;
w.write_bits(u64::from(self.repeat_indicator), 2)?;
w.write_bits(u64::from(self.mmsi.raw()), 30)?;
w.write_bits(0, 2)?; w.write_bits(u64::from(self.station_1_mmsi.raw()), 30)?;
encode_request(self.station_1_request_1, w)?;
let write_request_2 = self.station_1_request_2.is_some() || self.station_2.is_some();
if write_request_2 {
w.write_bits(0, 2)?; let request = self.station_1_request_2.unwrap_or(MessageRequest {
message_type: 0,
slot_offset: 0,
});
encode_request(request, w)?;
}
if let Some(station_2) = self.station_2 {
w.write_bits(0, 2)?; w.write_bits(u64::from(station_2.mmsi.raw()), 30)?;
encode_request(station_2.request, w)?;
}
Ok(())
}
}
fn decode_request(r: &mut BitReader<'_>) -> Result<MessageRequest, MessageError> {
let message_type = r.read_u8(6)?;
let slot_offset = r.read_u16(12)?;
Ok(MessageRequest {
message_type,
slot_offset,
})
}
fn encode_request(request: MessageRequest, w: &mut BitWriter<'_>) -> Result<(), BitError> {
w.write_bits(u64::from(request.message_type), 6)?;
w.write_bits(u64::from(request.slot_offset), 12)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn sample(
station_1_request_2: Option<MessageRequest>,
station_2: Option<SecondStation>,
) -> Interrogation {
Interrogation {
repeat_indicator: 0,
mmsi: Mmsi::from_raw(366_053_209),
station_1_mmsi: Mmsi::from_raw(366_999_999),
station_1_request_1: MessageRequest {
message_type: 5,
slot_offset: 100,
},
station_1_request_2,
station_2,
}
}
fn round_trip(original: Interrogation) -> Interrogation {
let mut buf = [0u8; 32];
let mut w = BitWriter::new(&mut buf);
original.encode(&mut w).unwrap();
let (armored, fill_bits) = w.finish().unwrap();
let mut r = BitReader::new(armored, fill_bits);
assert_eq!(r.read_u8(6).unwrap(), 15);
Interrogation::decode(&mut r).unwrap()
}
#[test]
fn round_trips_minimal() {
let original = sample(None, None);
assert_eq!(round_trip(original), original);
}
#[test]
fn round_trips_with_second_request_and_station() {
let original = sample(
Some(MessageRequest {
message_type: 18,
slot_offset: 50,
}),
Some(SecondStation {
mmsi: Mmsi::from_raw(111_222_333),
request: MessageRequest {
message_type: 24,
slot_offset: 75,
},
}),
);
assert_eq!(round_trip(original), original);
}
}