pub mod acas_and_fl_status;
pub mod acas_res_report;
pub mod aircraft_address;
pub mod aircraft_id;
pub mod bds_register_data;
pub mod data_source_id;
pub mod flight_level;
pub mod height_3d;
pub mod mode_1_code;
pub mod mode_1_confidence;
pub mod mode_2_code;
pub mod mode_2_confidence;
pub mod mode_3a_code;
pub mod mode_3a_confidence;
pub mod mode_c_code_conf;
pub mod positon_cart_coord;
pub mod positon_polar_coord;
pub mod radar_plot_charac;
pub mod radial_dopp_speed;
pub mod time_of_day;
pub mod tgt_report_desc;
pub mod track_number;
pub mod track_status;
pub mod track_quality;
pub mod velocity_polar_coord;
pub mod warning_errors;
use std::any::Any;
use std::ops::Range;
use std::{any::TypeId, collections::BTreeMap, fmt};
use bitvec::prelude::*;
use strum_macros::{AsRefStr, EnumString};
use crate::asterix::{category::CategoryIndex, message::AsterixMessageParseError};
use crate::asterix::uap::{common, UAPEntryLength};
use super::datatypes::{AsterixAttribute, AttributeProperties};
use bitvec::{order::Msb0, vec::BitVec};
pub mod constants {
pub const DATA_ITEM_PREFIX: char = 'I';
}
pub enum DataItemTypes {
DataSourceId { datasourceid: DataSourceId },
TargetReportDesc { targetreportdesc: TargetReportDesc },
WarnErrorConditions { warnerrorconditions: WarnErrorConditions },
PositionPolarCoord { positionpolarcoord: PositionPolarCoord },
PositionCartesianCoord { positioncartesiancoord: PositionCartesianCoord },
Mode2CodeOctal { mode2codeoctal: Mode2CodeOctal },
Mode1CodeOctal { mode1codeoctal: Mode1CodeOctal },
Mode2CodeConfid { mode2codeconfid: Mode2CodeConfid },
Mode1CodeConfid { mode1codeconfid: Mode1CodeConfid },
Mode3ACodeOctal { mode3acodeoctal: Mode3ACodeOctal },
Mode3AConfid { mode3aconfid: Mode3AConfid },
FlightLevelBin { flightlevelbin: FlightLevelBin },
ModeCCodeAndConfid { modeccodeandconfid: ModeCCodeAndConfid },
Height3DRadar { height3dradar: Height3DRadar },
RadialDopplerSpeed { radialdopplerspeed: RadialDopplerSpeed },
RadarPlotCharac { radarplotcharac: RadarPlotCharac },
TimeOfDday { timeofdday: TimeOfDday },
TrackNumber { tracknumber: TrackNumber },
TrackStatus { trackstatus: TrackStatus },
TrackVelocPolar { trackvelocpolar: TrackVelocPolar },
TrackQuality { trackquality: TrackQuality },
AircraftAddr { aircraftaddr: AircraftAddr },
CommACASAndFlitghtStatus { commacasandflitghtstatus: CommACASAndFlitghtStatus },
ACASResolReport { acasresolreport: ACASResolReport },
AircraftId { aircraftid: AircraftId },
ModeSMBData { modesmbdata: ModeSMBData },
SPF { spf: SPF },
REF { sref: REF }
}
#[derive(AsRefStr, Clone, Copy, Debug, PartialEq, EnumString)]
pub enum DataItemIndex {
_010,
_020,
_030,
_040,
_042,
_050,
_055,
_060,
_065,
_070,
_080,
_090,
_100,
_110,
_120,
_130,
_140,
_161,
_170,
_200,
_210,
_220,
_230,
_240,
_250,
_260,
_REF,
_SPF
}
#[derive(Clone)]
pub struct DataItem {
pub category: CategoryIndex,
pub data_item_index: DataItemIndex,
pub content: String,
pub type_id: TypeId,
pub length: UAPEntryLength
}
impl DataItem {
pub fn get_name(&self) -> String {
fmt::format(
format_args!("{}{}{}",
constants::DATA_ITEM_PREFIX,
self.category.as_str(),
self.data_item_index.as_ref()))
}
pub fn describe(&self) -> String {
fmt::format(
format_args!("{}{}{}: {:<50} : length: {:<15}",
constants::DATA_ITEM_PREFIX,
self.category.as_str(),
self.data_item_index.as_ref(),
self.content,
self.length.as_ref()))
}
}
pub trait DataItemStore {
fn set_octets(octets: &Vec<u8>);
fn get_octets() -> Vec<u8>;
fn get_size_in_octets() -> usize;
fn get_attribute_def() -> BTreeMap<u8, AttributeProperties>;
}
pub trait TDataItem {
fn get_attributes() -> Vec<AsterixAttribute>;
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError>;
}
pub struct DataSourceId;
impl TDataItem for DataSourceId {
fn get_attributes() -> Vec<AsterixAttribute> {
data_source_id::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct TargetReportDesc;
impl TDataItem for TargetReportDesc {
fn get_attributes() -> Vec<AsterixAttribute> {
tgt_report_desc::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
let len =common::get_extensible_data_item_length!(octets, start_index);
len
}
}
pub struct WarnErrorConditions;
impl TDataItem for WarnErrorConditions {
fn get_attributes() -> Vec<AsterixAttribute> {
warning_errors::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
common::get_extensible_data_item_length!(octets, start_index)
}
}
pub struct PositionPolarCoord;
impl TDataItem for PositionPolarCoord {
fn get_attributes() -> Vec<AsterixAttribute> {
positon_polar_coord::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(4)
}
}
pub struct PositionCartesianCoord;
impl TDataItem for PositionCartesianCoord {
fn get_attributes() -> Vec<AsterixAttribute> {
positon_cart_coord::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(4) }
}
pub struct Mode2CodeOctal;
impl TDataItem for Mode2CodeOctal {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_1_code::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct Mode1CodeOctal;
impl TDataItem for Mode1CodeOctal {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_2_code::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(1) }
}
pub struct Mode2CodeConfid;
impl TDataItem for Mode2CodeConfid {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_2_confidence::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct Mode1CodeConfid;
impl TDataItem for Mode1CodeConfid {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_1_confidence::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(1)
}
}
pub struct Mode3ACodeOctal;
impl TDataItem for Mode3ACodeOctal {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_3a_code::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct Mode3AConfid;
impl TDataItem for Mode3AConfid {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_3a_confidence::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct FlightLevelBin;
impl TDataItem for FlightLevelBin {
fn get_attributes() -> Vec<AsterixAttribute> {
flight_level::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct ModeCCodeAndConfid;
impl TDataItem for ModeCCodeAndConfid {
fn get_attributes() -> Vec<AsterixAttribute> {
mode_c_code_conf::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(4) }
}
pub struct Height3DRadar;
impl TDataItem for Height3DRadar {
fn get_attributes() -> Vec<AsterixAttribute> {
height_3d::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct RadialDopplerSpeed;
impl TDataItem for RadialDopplerSpeed {
fn get_attributes() -> Vec<AsterixAttribute> {
radial_dopp_speed::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
common::get_extensible_data_item_length!(octets, start_index)
}
}
pub struct RadarPlotCharac;
impl TDataItem for RadarPlotCharac {
fn get_attributes() -> Vec<AsterixAttribute> {
radar_plot_charac::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
use bitvec::prelude::*;
let mut len = 1 as usize;
let mut current_index = start_index;
let mut octet = octets[current_index];
loop {
let octet_bits = octet.view_bits::<Msb0>().to_bitvec();
let is_fx_set = octet_bits[0];
if is_fx_set {
len = len + 1;
current_index = current_index + 1;
octet = octets[current_index];
} else {
break;
}
}
Ok(len)
}
}
pub struct TimeOfDday;
impl TDataItem for TimeOfDday {
fn get_attributes() -> Vec<AsterixAttribute> {
time_of_day::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(3) }
}
pub struct TrackNumber;
impl TDataItem for TrackNumber {
fn get_attributes() -> Vec<AsterixAttribute> {
track_number::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct TrackStatus;
impl TDataItem for TrackStatus {
fn get_attributes() -> Vec<AsterixAttribute> {
track_status::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
common::get_extensible_data_item_length!(octets, start_index)
}
}
pub struct TrackVelocPolar;
impl TDataItem for TrackVelocPolar {
fn get_attributes() -> Vec<AsterixAttribute> {
velocity_polar_coord::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(4) }
}
pub struct TrackQuality;
impl TDataItem for TrackQuality {
fn get_attributes() -> Vec<AsterixAttribute> {
track_quality::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(4) }
}
pub struct AircraftAddr;
impl TDataItem for AircraftAddr {
fn get_attributes() -> Vec<AsterixAttribute> {
aircraft_address::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(3) }
}
pub struct CommACASAndFlitghtStatus;
impl TDataItem for CommACASAndFlitghtStatus {
fn get_attributes() -> Vec<AsterixAttribute> {
acas_and_fl_status::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(2) }
}
pub struct ACASResolReport;
impl TDataItem for ACASResolReport {
fn get_attributes() -> Vec<AsterixAttribute> {
acas_res_report::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(7) }
}
pub struct AircraftId;
impl TDataItem for AircraftId {
fn get_attributes() -> Vec<AsterixAttribute> {
aircraft_id::get_attributes!()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(6) }
}
pub struct ModeSMBData;
impl TDataItem for ModeSMBData {
fn get_attributes() -> Vec<AsterixAttribute> {
bds_register_data::get_attributes!()
}
fn get_length(octets: &Vec<u8>, start_index: usize) -> Result<usize, AsterixMessageParseError> {
let attributes = ModeSMBData::get_attributes();
let len = match common::get_repetitive_data_item_length!(octets, start_index, &attributes) {
Ok(s) => s,
Err(e) => return Err(e),
};
Ok(len)
}
}
pub struct SPF;
impl TDataItem for SPF {
fn get_attributes() -> Vec<AsterixAttribute> {
Vec::new()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(0) }
}
pub struct REF;
impl TDataItem for REF {
fn get_attributes() -> Vec<AsterixAttribute> {
Vec::new()
}
fn get_length(_octets: &Vec<u8>, _start_index: usize) -> Result<usize, AsterixMessageParseError> {
Ok(0) }
}
pub struct ConsumedDataItem {
pub length: usize,
pub octets: Vec<u8>
}
pub fn get_data_item(data_item: &DataItem, message_octets: &Vec<u8>, data_start_index: usize)
-> Result<ConsumedDataItem, AsterixMessageParseError> {
let data_item_length =
match get_data_item_length(data_item.type_id, message_octets, data_start_index) {
Some(s) => s,
None => return Err(AsterixMessageParseError::CouldNotRetrieveLength { dataitem: data_item.get_name() })
};
let range = data_start_index .. (data_start_index + data_item_length);
let octets = message_octets[range].iter().cloned().collect::<Vec<u8>>();
Ok(ConsumedDataItem {
length: data_item_length,
octets: octets
})
}
pub fn get_data_item_length(type_id: TypeId, octets: &Vec<u8>, start_index: usize) -> Option<usize> {
if type_id == TypeId::of::<DataSourceId>() {return Some(DataSourceId::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TimeOfDday>() { return Some(TimeOfDday::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TargetReportDesc>() { return Some(TargetReportDesc::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<PositionPolarCoord>() { return Some(PositionPolarCoord::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode3ACodeOctal>() { return Some(Mode3ACodeOctal::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<FlightLevelBin>() { return Some(FlightLevelBin::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<RadarPlotCharac>() { return Some(RadarPlotCharac::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<AircraftAddr>() { return Some(AircraftAddr::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<AircraftId>() { return Some(AircraftId::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<ModeSMBData>() { return Some(ModeSMBData::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TrackNumber>() { return Some(TrackNumber::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<PositionCartesianCoord>() { return Some(PositionCartesianCoord::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TrackVelocPolar>() { return Some(TrackVelocPolar::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TrackStatus>() { return Some(TrackStatus::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<TrackQuality>() { return Some(TrackQuality::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<WarnErrorConditions>() { return Some(WarnErrorConditions::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode3AConfid>() { return Some(Mode3AConfid::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<ModeCCodeAndConfid>() { return Some(ModeCCodeAndConfid::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Height3DRadar>() { return Some(Height3DRadar::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<RadialDopplerSpeed>() { return Some(RadialDopplerSpeed::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<CommACASAndFlitghtStatus>() { return Some(CommACASAndFlitghtStatus::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<ACASResolReport>() { return Some(ACASResolReport::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode1CodeOctal>() { return Some(Mode1CodeOctal::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode2CodeOctal>() { return Some(Mode2CodeOctal::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode1CodeConfid>() { return Some(Mode1CodeConfid::get_length(octets, start_index).unwrap()); }
if type_id == TypeId::of::<Mode2CodeConfid>() { return Some(Mode2CodeConfid::get_length(octets, start_index).unwrap()); }
None
}
pub fn get_data_item_attributes(type_id: TypeId) -> Option<Vec<AsterixAttribute>> {
if type_id == TypeId::of::<DataSourceId>() {return Some(DataSourceId::get_attributes()); }
if type_id == TypeId::of::<TimeOfDday>() { return Some(TimeOfDday::get_attributes()); }
if type_id == TypeId::of::<TargetReportDesc>() { return Some(TargetReportDesc::get_attributes()); }
if type_id == TypeId::of::<PositionPolarCoord>() { return Some(PositionPolarCoord::get_attributes()); }
if type_id == TypeId::of::<Mode3ACodeOctal>() { return Some(Mode3ACodeOctal::get_attributes()); }
if type_id == TypeId::of::<FlightLevelBin>() { return Some(FlightLevelBin::get_attributes()); }
if type_id == TypeId::of::<RadarPlotCharac>() { return Some(RadarPlotCharac::get_attributes()); }
if type_id == TypeId::of::<AircraftAddr>() { return Some(AircraftAddr::get_attributes()); }
if type_id == TypeId::of::<AircraftId>() { return Some(AircraftId::get_attributes()); }
if type_id == TypeId::of::<ModeSMBData>() { return Some(ModeSMBData::get_attributes()); }
if type_id == TypeId::of::<TrackNumber>() { return Some(TrackNumber::get_attributes()); }
if type_id == TypeId::of::<PositionCartesianCoord>() { return Some(PositionCartesianCoord::get_attributes()); }
if type_id == TypeId::of::<TrackVelocPolar>() { return Some(TrackVelocPolar::get_attributes()); }
if type_id == TypeId::of::<TrackStatus>() { return Some(TrackStatus::get_attributes()); }
if type_id == TypeId::of::<TrackQuality>() { return Some(TrackQuality::get_attributes()); }
if type_id == TypeId::of::<WarnErrorConditions>() { return Some(WarnErrorConditions::get_attributes()); }
if type_id == TypeId::of::<Mode3AConfid>() { return Some(Mode3AConfid::get_attributes()); }
if type_id == TypeId::of::<ModeCCodeAndConfid>() { return Some(ModeCCodeAndConfid::get_attributes()); }
if type_id == TypeId::of::<Height3DRadar>() { return Some(Height3DRadar::get_attributes()); }
if type_id == TypeId::of::<RadialDopplerSpeed>() { return Some(RadialDopplerSpeed::get_attributes()); }
if type_id == TypeId::of::<CommACASAndFlitghtStatus>() { return Some(CommACASAndFlitghtStatus::get_attributes()); }
if type_id == TypeId::of::<ACASResolReport>() { return Some(ACASResolReport::get_attributes()); }
if type_id == TypeId::of::<Mode1CodeOctal>() { return Some(Mode1CodeOctal::get_attributes()); }
if type_id == TypeId::of::<Mode2CodeOctal>() { return Some(Mode2CodeOctal::get_attributes()); }
if type_id == TypeId::of::<Mode1CodeConfid>() { return Some(Mode1CodeConfid::get_attributes()); }
if type_id == TypeId::of::<Mode2CodeConfid>() { return Some(Mode2CodeConfid::get_attributes()); }
None
}
pub fn get_attributes_from_dataitem(data_item: &DataItem, consumed_data: &ConsumedDataItem)
-> Option<BTreeMap<String, AttributeProperties>> {
let attributes = get_data_item_attributes(data_item.type_id).unwrap();
let data_item_prefix = data_item.get_name();
let mut attribute_properties = BTreeMap::<String, AttributeProperties>::new();
let mut last_consumed_octet = 0 as usize;
let mut last_len: usize;
let mut last_field = attributes[0].field;
let mut len: usize = attributes[0].octets_len as usize;
let mut range: Range<usize> = last_consumed_octet..last_consumed_octet+len;
let mut attribute_octets= consumed_data.octets[range].iter().clone().as_slice();
for attribute in &attributes {
if last_field != attribute.field {
last_field = attribute.field;
last_len = len;
len = attribute.octets_len as usize;
last_consumed_octet = last_consumed_octet + last_len;
if data_item.length.type_id() == (UAPEntryLength::Variable { size_first: 1 }).type_id() &&
consumed_data.octets.len() < (last_consumed_octet + len) {
break;
}
range = last_consumed_octet..last_consumed_octet+len;
attribute_octets = consumed_data.octets[range].iter().clone().as_slice();
}
let attribute_property = AttributeProperties {
field_key: fmt::format(format_args!("{}_{}", &data_item_prefix, &attribute.name)),
bits: get_attribute_bits(attribute, attribute_octets)
};
attribute_properties.insert(attribute_property.field_key.clone(), attribute_property);
}
Some(attribute_properties)
}
pub fn get_msb_bits(octets: &[u8]) -> BitVec::<u8, Msb0> {
let bv = (octets).view_bits::<Msb0>().to_bitvec();
bv
}
pub fn get_lsb_bits(octets: &[u8]) -> BitVec::<u8, Lsb0> {
let bv = (octets).view_bits::<Lsb0>().to_bitvec();
bv
}
pub fn get_bitvec_subset_as_msb0(bv: &BitVec<u8,Msb0>, msb_index:usize , lsb_index: usize) -> BitVec::<u8, Msb0> {
let range_begin = bv.len() - (msb_index);
let range_end = bv.len() - (lsb_index - 1);
let bv_slice = bv.as_bitslice();
let attribute_slice = match bv_slice.get(range_begin .. range_end) {
Some(bs) => bs,
None => BitSlice::empty(),
};
let mut attribute_bits:BitVec::<u8, Msb0> = attribute_slice.to_bitvec();
attribute_bits.reverse();
attribute_bits
}
fn get_attribute_bits(attribute: &AsterixAttribute, attribute_octets: &[u8]) -> BitVec::<u8, Msb0> {
let bv = get_msb_bits(attribute_octets);
let attribute_bits = get_bitvec_subset_as_msb0(&bv, attribute.initial_bit as usize, attribute.final_bit as usize);
attribute_bits
}
pub fn get_expected_bits_from_u8_vec(vec_u8: &Vec<u8>) -> BitVec<u8, Msb0> {
let bitvec = get_msb_bits(vec_u8.as_slice());
bitvec
}
pub mod tests {
#[test]
fn test_sac_bits() {
use crate::asterix::uap::common::datatypes::AsterixAttribute;
use crate::asterix::uap::common::datatypes::AttributeType;
let attribute = AsterixAttribute::new(1, 1, 8, 1, "(SAC) System Area Code".to_string(), "sac".to_string(), AttributeType::UInt16);
let attribute_octets = vec![0b00011001_u8];
let bits = super::get_attribute_bits(&attribute, &attribute_octets);
let octets_bits = super::get_expected_bits_from_u8_vec(&attribute_octets);
let expected_bits = super::get_bitvec_subset_as_msb0(&octets_bits, 8, 1);
assert_eq!(expected_bits, bits, "{} bits should match", attribute.name);
}
#[test]
fn test_mode3a_code_bits() {
use crate::asterix::uap::common::datatypes::AsterixAttribute;
use crate::asterix::uap::common::datatypes::AttributeType;
let v_attr = AsterixAttribute::new(2, 1, 16, 16, "(V) Code Validated".to_string(), "validated".to_string(), AttributeType::Boolean);
let g_attr = AsterixAttribute::new(2, 2, 15, 15, "(G) Garbled Code".to_string(), "garbled".to_string(), AttributeType::Boolean);
let l_attr = AsterixAttribute::new(2, 3, 14, 14, "(L) Mode-3/A Code Absent".to_string(), "not_extracted".to_string(), AttributeType::Boolean);
let m3_attr = AsterixAttribute::new(2, 4, 12, 1, "Mode-3/A reply in octal".to_string(), "mode_3a_reply".to_string(), AttributeType::UInt16);
let attribute_octets = vec![0b11100010_u8, 0b00000000];
let octets_bits = super::get_expected_bits_from_u8_vec(&attribute_octets);
let expected_bits = super::get_bitvec_subset_as_msb0(&octets_bits, 16, 16);
let v_attr_bits = super::get_attribute_bits(&v_attr, &attribute_octets);
assert_eq!(expected_bits, v_attr_bits, "{} bits should match", v_attr.name);
let expected_bits = super::get_bitvec_subset_as_msb0(&octets_bits, 15, 15);
let g_attr_bits = super::get_attribute_bits(&g_attr, &attribute_octets);
assert_eq!(expected_bits, g_attr_bits, "{} bits should match", g_attr.name);
let expected_bits = super::get_bitvec_subset_as_msb0(&octets_bits, 14, 14);
let l_attr_bits = super::get_attribute_bits(&l_attr, &attribute_octets);
assert_eq!(expected_bits, l_attr_bits, "{} bits should match", l_attr.name);
let expected_bits = super::get_bitvec_subset_as_msb0(&octets_bits, 12, 1);
let m3_attr_bits = super::get_attribute_bits(&m3_attr, &attribute_octets);
assert_eq!(expected_bits, m3_attr_bits, "{} bits should match", m3_attr.name);
}
#[test]
fn test_bits_retrieval() {
use std::fmt;
let trim_characters: &[_] = &['[', ']', ' ', ','][..];
let array_with_one_octet = [0b1111_0000 as u8];
let array_with_two_octet = [0b1111_0000 as u8, 0b0000_1111];
let lsb_bits = super::get_lsb_bits(&array_with_one_octet);
let bits_as_string = fmt::format(format_args!("{:b}", &lsb_bits)).replace(trim_characters, "");
assert_eq!("00001111", bits_as_string);
let lsb_bits = super::get_lsb_bits(&array_with_two_octet);
let bits_as_string = fmt::format(format_args!("{:b}", &lsb_bits)).replace(trim_characters, "");
assert_eq!("0000111111110000", bits_as_string);
let msb_bits = super::get_msb_bits(&array_with_one_octet);
let bits_as_string = fmt::format(format_args!("{:b}", &msb_bits)).replace(trim_characters, "");
assert_eq!("11110000", bits_as_string);
let msb_bits = super::get_msb_bits(&array_with_two_octet);
let bits_as_string = fmt::format(format_args!("{:b}", &msb_bits)).replace(trim_characters, "");
assert_eq!("1111000000001111", bits_as_string);
}
}