use deku::prelude::*;
use serde::{Deserialize, Serialize};
use super::converters::*;
fn read_remaining_data_before_radio<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);
}
if data.len() >= 3 {
data.truncate(data.len() - 3);
} else {
data.clear();
}
Ok(data)
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct MultipleSlotBinaryAddressedStructured {
#[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_before_radio(deku::reader)")]
pub data: Vec<u8>,
#[deku(bits = "20")]
pub radio: u32,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct MultipleSlotBinaryBroadcastStructured {
#[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_before_radio(deku::reader)")]
pub data: Vec<u8>,
#[deku(bits = "20")]
pub radio: u32,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct MultipleSlotBinaryAddressedUnstructured {
#[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_before_radio(deku::reader)")]
pub data: Vec<u8>,
#[deku(bits = "20")]
pub radio: u32,
}
#[derive(Debug, Clone, PartialEq, DekuRead, Serialize, Deserialize)]
#[deku(endian = "big")]
pub struct MultipleSlotBinaryBroadcastUnstructured {
#[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_before_radio(deku::reader)")]
pub data: Vec<u8>,
#[deku(bits = "20")]
pub radio: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MultipleSlotBinaryMessage {
AddressedStructured(MultipleSlotBinaryAddressedStructured),
BroadcastStructured(MultipleSlotBinaryBroadcastStructured),
AddressedUnstructured(MultipleSlotBinaryAddressedUnstructured),
BroadcastUnstructured(MultipleSlotBinaryBroadcastUnstructured),
}
impl MultipleSlotBinaryMessage {
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] & 0x03;
let addressed = (flags & 0x01) != 0; let structured = (flags & 0x02) != 0;
match (addressed, structured) {
(true, true) => {
let (remaining, msg) = MultipleSlotBinaryAddressedStructured::from_bytes(data)?;
Ok((
remaining,
MultipleSlotBinaryMessage::AddressedStructured(msg),
))
}
(false, true) => {
let (remaining, msg) = MultipleSlotBinaryBroadcastStructured::from_bytes(data)?;
Ok((
remaining,
MultipleSlotBinaryMessage::BroadcastStructured(msg),
))
}
(true, false) => {
let (remaining, msg) = MultipleSlotBinaryAddressedUnstructured::from_bytes(data)?;
Ok((
remaining,
MultipleSlotBinaryMessage::AddressedUnstructured(msg),
))
}
(false, false) => {
let (remaining, msg) = MultipleSlotBinaryBroadcastUnstructured::from_bytes(data)?;
Ok((
remaining,
MultipleSlotBinaryMessage::BroadcastUnstructured(msg),
))
}
}
}
pub fn asdict(&self) -> serde_json::Value {
match self {
MultipleSlotBinaryMessage::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,
"radio": msg.radio,
})
}
MultipleSlotBinaryMessage::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,
"radio": msg.radio,
})
}
MultipleSlotBinaryMessage::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,
"app_id": msg.app_id,
"data": msg.data,
"radio": msg.radio,
})
}
MultipleSlotBinaryMessage::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,
"radio": msg.radio,
})
}
}
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
serde_json::to_string(self)
}
pub fn msg_type(&self) -> u8 {
26
}
pub fn mmsi(&self) -> u32 {
match self {
MultipleSlotBinaryMessage::AddressedStructured(msg) => msg.mmsi,
MultipleSlotBinaryMessage::BroadcastStructured(msg) => msg.mmsi,
MultipleSlotBinaryMessage::AddressedUnstructured(msg) => msg.mmsi,
MultipleSlotBinaryMessage::BroadcastUnstructured(msg) => msg.mmsi,
}
}
}
impl DekuReader<'_, ()> for MultipleSlotBinaryMessage {
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)
}
}