pub mod cat048;
pub mod parser;
use std::collections::BTreeMap;
use custom_error::custom_error;
use crate::asterix::uap::common::dataitems::DataItemIndex;
use crate::asterix::uap::providers::Provider;
use crate::asterix::uap::UAPDataItem;
use crate::asterix::uap::common::dataitems::DataItem;
use crate::asterix::uap::common::dataitems::get_lsb_bits;
use crate::asterix::category::CategoryIndex;
use self::constants::*;
use super::uap_json::structures::Attribute;
pub mod constants {
pub const MESSAGE_CAT_OCTET_INDEX: usize = 0;
pub const MESSAGE_LEN_OCTET_INDEX: usize = 1;
pub const MESSAGE_FSPEC_OCTET_START_INDEX: usize = 3;
pub const MAP_ICAO_CHARACTERS: &'static [char] = &[
'#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#', '#', '#',
'#', '#', ' ', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', '#', '#',
'#', '#', '#', '#'];
}
pub struct MessageDataItem {
pub frn: u8,
pub presence: bool,
pub data_item: DataItem,
}
custom_error!{ pub AsterixMessageParseError
InvalidCategory{category: u8, provider: Provider} = "CAT {category} for provider {provider} is not yet implemented",
InvalidLength{provided_len: usize, stream_len: usize } = "The provided messsage length [{provided_len}] does not comply with message stream length [{stream_len}]",
InvalidRepetitiveFieldLength{size: usize} = "The provided reptitive field length is invalid [{size}]",
CouldNotRetrieveLength{dataitem: String} = "The provided data item [{dataitem}] could not return a valid length",
OtherError = "Some other error has occurred"
}
pub struct AsterixMessage {
pub code: String,
pub description: String,
pub provider: String,
pub attributes_map: BTreeMap<String, Attribute>
}
impl AsterixMessage {
pub fn new(
code: String,
description: String,
provider: String,
attributes: BTreeMap<String, Attribute>) -> Self {
Self { code, description, provider, attributes_map: attributes }
}
fn _get_message_data_items(message_octets: &Vec<u8>, uap_data_items: Vec<UAPDataItem>) -> (usize, Vec<MessageDataItem>) {
let mut message_data_items = Vec::<MessageDataItem>::new();
let mut data_start_index = MESSAGE_FSPEC_OCTET_START_INDEX + 1;
let mut octet_index: usize = MESSAGE_FSPEC_OCTET_START_INDEX;
let mut data_item_index = 1;
for data_item in uap_data_items {
let message_data_item = MessageDataItem {
presence: false,
frn: data_item.frn,
data_item: data_item.data_item
};
message_data_items.push(message_data_item);
}
let mut has_more_fspec = true;
while has_more_fspec == true {
let fspec = message_octets[octet_index];
let fspec_bits = get_lsb_bits(&[fspec]);
has_more_fspec = fspec_bits[7]; (1..9 as usize).for_each(|i| {
let fspec_item_index = 8-i;
let is_present = fspec_bits[fspec_item_index];
if i == 8 { if !is_present {
has_more_fspec = false;
} else {
octet_index += 1; data_start_index += 1; }
}
else {
message_data_items[data_item_index-1].presence = is_present;
data_item_index = data_item_index + 1; }
});
}
return (data_start_index, message_data_items);
}
}
fn _assert_uap_items_presence(uap_definition: &Vec<MessageDataItem>) {
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_010, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_140, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_020, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_040, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_070, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_090, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_130, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_220, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_240, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_250, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_161, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_042, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_200, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_170, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_210, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_030, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_080, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_100, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_110, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_120, uap_definition));
assert_eq!(true, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_230, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_260, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_055, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_050, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_065, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_060, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_SPF, uap_definition));
assert_eq!(false, _find_data_item_presence(CategoryIndex::_048, DataItemIndex::_REF, uap_definition));
}
fn _find_data_item_presence(category_index: CategoryIndex, data_item_index: DataItemIndex, uap_definition: &Vec<MessageDataItem>) -> bool {
let uap_data_item
= uap_definition.into_iter()
.find(|x|
x.data_item.category == category_index &&
x.data_item.data_item_index == data_item_index).unwrap() ;
return uap_data_item.presence;
}