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 130 131
//! 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 Vec<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(),
}
}
}