1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! Encode/Decode for ASTERIX protocol using the deku library
//!
//! # Creating an Asterix packet
//! There are currently two ways of creating an AsterixPacket:
//!
//! ## From `&[u8]`
//! ```
//! use deku::prelude::*;
//! use asterix::*;
//! use asterix::data_item::*;
//!
//! let bytes = &[0x22, 0x00, 0x0b, 0xf0, 0x19, 0x0d, 0x02, 0x35, 0x6d, 0xfa, 0x60];
//! let (_, mut packet) = AsterixPacket::from_bytes((bytes, 0)).unwrap();
//! ```
//!
//! ## Packet Creation
//! Create an CAT34 Asterix packet.
//!
//! ```rust
//! use deku::prelude::*;
//! use asterix::*;
//! use asterix::data_item::*;
//! use asterix::types::*;
//!
//! let mut thirty_eight = Cat34::default();
//! thirty_eight.data_source_identifier = Some(DataSourceIdentifier { sac: 25, sic: 13 });
//! thirty_eight.message_type = Some(MessageType {
//! t: MTYPE::SectorCrossing,
//! });
//! thirty_eight.time_of_day = Some(TimeOfDay { time: 27355.953 });
//! thirty_eight.sector_number = Some(SectorNumber { num: 135 });
//!
//! let mut packet = AsterixPacket::default();
//! packet.category = 34;
//! packet.messages = vec![asterix::AsterixMessage::Cat34(thirty_eight)];
//! ```
//!
//! # Encoding Packets
//! ```rust
//! use deku::prelude::*;
//! use asterix::*;
//! use asterix::data_item::*;
//!
//! // Create / Mutate a packet
//! let mut packet = AsterixPacket::default();
//!
//! // finalize(): Updates fspec for all packet messages, as well as setting the length as per
//! // the protocol.
//! packet.finalize().unwrap();
//!
//! // serialize
//! packet.to_bytes().unwrap();
//! ```
use deku::bitvec::{BitVec, Msb0};
use deku::prelude::*;
pub mod types;
mod custom_read_write;
mod modifier;
mod fourty_eight;
pub use fourty_eight::Cat48;
mod thirty_four;
pub use thirty_four::Cat34;
pub mod data_item;
mod fspec;
/// Size of category + length in bytes
const ASTERIX_HEADER_SIZE: u16 = 3;
const FSPEC_IDENT: u8 = 0b0000_0001;
#[derive(Debug, Default, PartialEq, DekuRead, DekuWrite)]
#[deku(endian = "big")]
pub struct AsterixPacket {
/// Category of all `messages`
pub category: u8,
/// Total length of `AsterixPacket`
#[deku(update = "Self::update_len(&mut self.messages)")]
pub length: u16,
/// Asterix Messages
#[deku(bytes_read = "length - ASTERIX_HEADER_SIZE", ctx = "*category")]
pub messages: Vec<AsterixMessage>,
}
impl AsterixPacket {
/// Update fspec and len
pub fn finalize(&mut self) -> Result<(), DekuError> {
for message in &mut self.messages {
message.update_fspec();
}
self.update()
}
/// Read all messages and return byte len
fn update_len(messages: &mut [AsterixMessage]) -> u16 {
let mut len: u16 = 0;
for message in messages.iter_mut() {
let mut bits: BitVec<u8, Msb0> = BitVec::new();
message.write(&mut bits, (deku::ctx::Endian::Big, 0)).unwrap();
len += (bits.len() / 8) as u16 + ASTERIX_HEADER_SIZE
}
len
}
}
#[derive(Debug, PartialEq, DekuRead, DekuWrite)]
#[deku(id = "category", ctx = "_: deku::ctx::Endian, category: u8")]
/// Union of Asterix categories
pub enum AsterixMessage {
#[deku(id = "34")]
Cat34(Cat34),
#[deku(id = "48")]
Cat48(Cat48),
}
impl AsterixMessage {
/// Call `update_fpsec` of internal type
pub fn update_fspec(&mut self) {
match self {
Self::Cat34(c) => c.update_fspec(),
Self::Cat48(c) => c.update_fspec(),
}
}
}