use deku::prelude::*;
use serde::{Deserialize, Serialize};
use super::converters::*;
fn read_remaining_data<R: std::io::Read + std::io::Seek>(
reader: &mut Reader<R>,
) -> Result<Vec<u8>, DekuError> {
let mut data = Vec::new();
while let Ok(byte) = u8::from_reader_with_ctx(reader, ()) {
data.push(byte);
}
Ok(data)
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct SingleSlotBinaryAddressedStructured {
#[deku(bits = "6")]
pub msg_type: u8,
#[deku(bits = "2")]
pub repeat: u8,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub mmsi: u32,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub addressed: bool,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub structured: bool,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub dest_mmsi: u32,
#[deku(bits = "16")]
pub app_id: u16,
#[deku(reader = "read_remaining_data(deku::reader)")]
pub data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct SingleSlotBinaryBroadcastStructured {
#[deku(bits = "6")]
pub msg_type: u8,
#[deku(bits = "2")]
pub repeat: u8,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub mmsi: u32,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub addressed: bool,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub structured: bool,
#[deku(bits = "16")]
pub app_id: u16,
#[deku(reader = "read_remaining_data(deku::reader)")]
pub data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct SingleSlotBinaryAddressedUnstructured {
#[deku(bits = "6")]
pub msg_type: u8,
#[deku(bits = "2")]
pub repeat: u8,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub mmsi: u32,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub addressed: bool,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub structured: bool,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub dest_mmsi: u32,
#[deku(reader = "read_remaining_data(deku::reader)")]
pub data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct SingleSlotBinaryBroadcastUnstructured {
#[deku(bits = "6")]
pub msg_type: u8,
#[deku(bits = "2")]
pub repeat: u8,
#[deku(
bits = "30",
map = "|x: u32| -> Result<_, DekuError> { Ok(from_mmsi(x)) }"
)]
pub mmsi: u32,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub addressed: bool,
#[deku(bits = "1", map = "|x: u8| -> Result<_, DekuError> { Ok(x != 0) }")]
pub structured: bool,
#[deku(reader = "read_remaining_data(deku::reader)")]
pub data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum SingleSlotBinaryMessage {
AddressedStructured(SingleSlotBinaryAddressedStructured),
BroadcastStructured(SingleSlotBinaryBroadcastStructured),
AddressedUnstructured(SingleSlotBinaryAddressedUnstructured),
BroadcastUnstructured(SingleSlotBinaryBroadcastUnstructured),
}
impl SingleSlotBinaryMessage {
fn from_bytes(data: (&[u8], usize)) -> Result<((&[u8], usize), Self), DekuError> {
let (bytes, _bit_offset) = data;
if bytes.len() < 5 {
return Err(DekuError::Incomplete(deku::error::NeedSize::new(5 * 8)));
}
let flags = (bytes[4] >> 6) & 0x03;
let addressed = (flags & 0x02) != 0; let structured = (flags & 0x01) != 0;
match (addressed, structured) {
(true, true) => {
let (remaining, msg) = SingleSlotBinaryAddressedStructured::from_bytes(data)?;
Ok((remaining, SingleSlotBinaryMessage::AddressedStructured(msg)))
}
(false, true) => {
let (remaining, msg) = SingleSlotBinaryBroadcastStructured::from_bytes(data)?;
Ok((remaining, SingleSlotBinaryMessage::BroadcastStructured(msg)))
}
(true, false) => {
let (remaining, msg) = SingleSlotBinaryAddressedUnstructured::from_bytes(data)?;
Ok((
remaining,
SingleSlotBinaryMessage::AddressedUnstructured(msg),
))
}
(false, false) => {
let (remaining, msg) = SingleSlotBinaryBroadcastUnstructured::from_bytes(data)?;
Ok((
remaining,
SingleSlotBinaryMessage::BroadcastUnstructured(msg),
))
}
}
}
}
impl DekuReader<'_, ()> for SingleSlotBinaryMessage {
fn from_reader_with_ctx<R: std::io::Read + std::io::Seek>(
reader: &mut Reader<R>,
_ctx: (),
) -> Result<Self, DekuError> {
let mut data = Vec::new();
while let Ok(byte) = u8::from_reader_with_ctx(reader, ()) {
data.push(byte);
}
let (_, msg) = Self::from_bytes((&data, 0))?;
Ok(msg)
}
}
impl SingleSlotBinaryMessage {
pub fn asdict(&self) -> serde_json::Value {
match self {
SingleSlotBinaryMessage::AddressedStructured(msg) => {
serde_json::json!({
"msg_type": msg.msg_type,
"repeat": msg.repeat,
"mmsi": msg.mmsi,
"addressed": msg.addressed,
"structured": msg.structured,
"dest_mmsi": msg.dest_mmsi,
"app_id": msg.app_id,
"data": msg.data,
})
}
SingleSlotBinaryMessage::BroadcastStructured(msg) => {
serde_json::json!({
"msg_type": msg.msg_type,
"repeat": msg.repeat,
"mmsi": msg.mmsi,
"addressed": msg.addressed,
"structured": msg.structured,
"app_id": msg.app_id,
"data": msg.data,
})
}
SingleSlotBinaryMessage::AddressedUnstructured(msg) => {
serde_json::json!({
"msg_type": msg.msg_type,
"repeat": msg.repeat,
"mmsi": msg.mmsi,
"addressed": msg.addressed,
"structured": msg.structured,
"dest_mmsi": msg.dest_mmsi,
"data": msg.data,
})
}
SingleSlotBinaryMessage::BroadcastUnstructured(msg) => {
serde_json::json!({
"msg_type": msg.msg_type,
"repeat": msg.repeat,
"mmsi": msg.mmsi,
"addressed": msg.addressed,
"structured": msg.structured,
"data": msg.data,
})
}
}
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(self)
}
pub fn msg_type(&self) -> u8 {
25
}
pub fn mmsi(&self) -> u32 {
match self {
SingleSlotBinaryMessage::AddressedStructured(msg) => msg.mmsi,
SingleSlotBinaryMessage::BroadcastStructured(msg) => msg.mmsi,
SingleSlotBinaryMessage::AddressedUnstructured(msg) => msg.mmsi,
SingleSlotBinaryMessage::BroadcastUnstructured(msg) => msg.mmsi,
}
}
}