Skip to content

Commit

Permalink
Merge pull request #20 from salsabiljb/Binary_Acknowledge_Message_Type_7
Browse files Browse the repository at this point in the history
feat: add support for msg type 7
  • Loading branch information
squidpickles authored Sep 10, 2024
2 parents d60f303 + 8326838 commit 1905098
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 1 deletion.
113 changes: 113 additions & 0 deletions src/messages/binary_acknowledge.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//! Binary Acknowledge (type 7)
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
use super::nom_noalloc::many_m_n;
use super::AisMessageType;
use crate::errors::Result;
use crate::lib;
use nom::bits::{bits, complete::take as take_bits};
#[cfg(any(feature = "std", feature = "alloc"))]
use nom::multi::many_m_n;
use nom::IResult;

#[derive(Debug, PartialEq, Eq)]
pub struct Acknowledgement {
pub mmsi: u32,
pub seq_num: u8,
}

impl Acknowledgement {
pub fn parse(data: (&[u8], usize)) -> IResult<(&[u8], usize), Self> {
let (data, mmsi) = take_bits(30u32)(data)?;
let (data, seq_num) = take_bits(2u8)(data)?;
Ok((data, Self { mmsi, seq_num }))
}
}

#[cfg(any(feature = "std", feature = "alloc"))]
pub type AcknowledgementList = lib::std::vec::Vec<Acknowledgement>;
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
pub type AcknowledgementList = lib::std::vec::Vec<Acknowledgement, 4>;

#[derive(Debug, PartialEq, Eq)]
pub struct BinaryAcknowledge {
pub message_type: u8,
pub repeat_indicator: u8,
pub mmsi: u32,
pub acks: AcknowledgementList,
}

impl<'a> AisMessageType<'a> for BinaryAcknowledge {
fn name(&self) -> &'static str {
"Binary Acknowledge"
}

fn parse(data: &'a [u8]) -> Result<Self> {
let (_, report) = parse_base(data)?;
Ok(report)
}
}

fn parse_base<'a>(data: &'a [u8]) -> IResult<&'a [u8], BinaryAcknowledge> {
bits(move |data: (&'a [u8], usize)| -> IResult<_, _> {
let (data, message_type) = take_bits(6u8)(data)?;
let (data, repeat_indicator) = take_bits(2u8)(data)?;
let (data, mmsi) = take_bits(30u32)(data)?;
let (data, _spare) = take_bits::<_, u8, _, _>(2u8)(data)?;

#[cfg(any(feature = "std", feature = "alloc"))]
let (data, acks) = many_m_n(1, 4, Acknowledgement::parse)(data)?;
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
let (data, acks) = many_m_n::<_, _, _, _, 4>(1, Acknowledgement::parse)(data)?;

Ok((
data,
BinaryAcknowledge {
message_type,
repeat_indicator,
mmsi,
acks,
},
))
})(data)
}

#[cfg(test)]
mod tests {
#![allow(clippy::unreadable_literal)]
use super::*;

#[test]
fn test_type7_example_1() {
let bytestream = b"702R5`hwCt40";
let bitstream = crate::messages::unarmor(bytestream, 0).unwrap();
let report = BinaryAcknowledge::parse(bitstream.as_ref()).unwrap();

assert_eq!(report.message_type, 7);
assert_eq!(report.repeat_indicator, 0);
assert_eq!(report.mmsi, 2655651);
assert_eq!(report.acks.len(), 1);
let ack = &report.acks[0];
assert_eq!(ack.mmsi, 265547840);
assert_eq!(ack.seq_num, 0);
}

#[test]
fn test_type7_example_2() {
let bytestream = b"702R5`hwCjq8";
let bitstream = crate::messages::unarmor(bytestream, 0).unwrap();
let report = BinaryAcknowledge::parse(bitstream.as_ref()).unwrap();

assert_eq!(report.message_type, 7);
assert_eq!(report.repeat_indicator, 0);
assert_eq!(report.mmsi, 2655651);
assert_eq!(report.acks.len(), 1);
let ack = &report.acks[0];
assert_eq!(ack.mmsi, 265538450);
assert_eq!(ack.seq_num, 0);

// Ensure other MMSIs are not present
assert!(report.acks.get(1).is_none());
assert!(report.acks.get(2).is_none());
assert!(report.acks.get(3).is_none());
}
}
6 changes: 5 additions & 1 deletion src/messages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub mod static_data_report;
pub mod types;
pub mod utc_date_response;
pub mod standard_aircraft_position_report;

pub mod binary_acknowledge;
pub use parsers::message_type;

#[cfg(feature = "alloc")]
Expand All @@ -44,6 +44,7 @@ pub enum AisMessage {
StaticDataReport(static_data_report::StaticDataReport),
UtcDateResponse(utc_date_response::UtcDateResponse),
StandardAircraftPositionReport(standard_aircraft_position_report::SARPositionReport),
BinaryAcknowledgeMessage(binary_acknowledge::BinaryAcknowledge),
}

/// Trait that describes specific types of AIS messages
Expand All @@ -70,6 +71,9 @@ pub fn parse(unarmored: &[u8]) -> Result<AisMessage> {
5 => Ok(AisMessage::StaticAndVoyageRelatedData(
static_and_voyage_related_data::StaticAndVoyageRelatedData::parse(unarmored)?,
)),
7 => Ok(AisMessage::BinaryAcknowledgeMessage(
binary_acknowledge::BinaryAcknowledge::parse(unarmored)?,
)),
8 => Ok(AisMessage::BinaryBroadcastMessage(
binary_broadcast_message::BinaryBroadcastMessage::parse(unarmored)?,
)),
Expand Down

0 comments on commit 1905098

Please sign in to comment.