asterix_parser 0.1.1

Playground do Protocolo ASTERIX
Documentation
use std::collections::BTreeMap;
use std::env;

use asterix_parser::asterix::category::CategoryKey;
use asterix_parser::asterix::message::parser::parse_message;
use asterix_parser::asterix::uap::common::dataitems::get_bitvec_subset_as_msb0;
use asterix_parser::asterix::uap::common::dataitems::get_msb_bits;
use asterix_parser::asterix::uap_json::structures::Attribute;
use asterix_parser::asterix::uap_json::structures::DataRecord;
use asterix_parser::asterix::uap_json::structures::Edition;
use bitvec::prelude::*;

use asterix_parser::asterix::category::CategoryIndex;
use asterix_parser::asterix::message::cat048;
use asterix_parser::asterix::message::AsterixMessage;
use asterix_parser::asterix::uap::providers::Provider;
use asterix_parser::asterix::Context;

#[test]
fn it_parse_cat048_message() -> anyhow::Result<()> {

    let curdir = env::current_dir().unwrap();
    println!("Running test from folder: {:?}", curdir.to_str());

    let mut message_bytes: Vec<u8> = vec![];
    message_bytes.append(&mut vec![0x30, 0x00, 0x30, 0xFD, 
                                   0xF7, 0x02, 0x19, 0xC9,
                                   0x35, 0x6D, 0x4D, 0xA0, 
                                   0xC5, 0xAF, 0xF1, 0xE0, 
                                   0x02, 0x00, 0x05, 0x28, 
                                   0x3C, 0x66, 0x0C, 0x10, 
                                   0xC2, 0x36, 0xD4, 0x18, 
                                   0x20, 0x01, 0xC0, 0x78, 
                                   0x00, 0x31, 0xBC, 0x00, 
                                   0x00, 0x40, 0x0D, 0xEB, 
                                   0x07, 0xB9, 0x58, 0x2E, 
                                   0x41, 0x00, 0x20, 0xF5]); 

    let explanatory_message = cat048::get_example_message();
    assert_eq!(message_bytes, explanatory_message);

    let asterix_context = Context::new()?;
    let cat_key = CategoryKey {
        index: CategoryIndex::_048,
        edition: Edition { major: 1, minor: 31 },
        provider: Provider::Standard
    };

    assert!(asterix_context.uap_definitions.contains_key(&cat_key), "UAP definitions should contains one CAT048 entry");

    let uap_048_collection: Vec<_> = asterix_context.uap_definitions.keys()
    .into_iter()
    .filter(|x| x.index == CategoryIndex::_048).collect();

    assert_eq!(true, uap_048_collection.len() > 0, "CAT048 definition should be greather than 0");
    assert_eq!(true, uap_048_collection.into_iter().filter(| p | p.provider == Provider::Standard).count() > 0);

    let cat048_uap_def_opt: Option<(CategoryKey, DataRecord)> 
        = asterix_context.uap_definitions
                .into_iter()
                .find(|x| x.0 == cat_key);
    assert_eq!(true, cat048_uap_def_opt.is_some(), "Should have found an UAP definiton for CAT048, provider == Standard");

    let cat048_uap_definition = cat048_uap_def_opt.unwrap().1;
    assert_eq!(28, cat048_uap_definition.catalogue.len(), "Should have 28 data item entries");

    let debugging: bool = false; 
    let _message =  parse_message(&cat048_uap_definition, &message_bytes, debugging);
    
    /*
    assert_eq!("CAT048", message.code);
    assert_eq!(Provider::Standard.as_ref(), message.provider);
    assert_eq!(13, message.data_items_store.len());
    assert_eq!(50, message.attributes.len());
    */
    //    assert_attributes(&message);

    Ok(())
    // check_attributes(&message, &message_bytes);
    //assert_eq!(true, message.code(&CategoryIndex::_048));
}

/* fn check_attributes(message: &AsterixMessage, message_bytes: &Vec<u8>) {
    for attribute in message.attributes.values() {
        get_bitvector_from_message(attribute, message_bytes);
        let key = &attribute.field_key;
        let elements: Vec<&str> = key.split("_").collect();
        let category_index = CategoryIndex::from_str(&elements[0][1..]).unwrap();
        let data_item_index = DataItemIndex::from_str(elements[1]).unwrap();
        // println!("key: {}, elements: [0:{}]. [1:{}], [2:{}]", key, elements[0], elements[1], elements[2]);
        let data_item : &DataItem = uap_dataitems.into_iter()
            .filter(|x| x.data_item.category == category_index &&
                                       x.data_item.data_item_index == data_item_index).collect();

        let attribute_definitions = get_data_item_attributes(data_item.type_id).unwrap();
        
        let attribute_definition: AsterixAttribute = attribute_definitions.into_iter()
                                    .filter(|x| x.name == elements[2]).collect();
         
            
    }
} */

fn _assert_attributes(message: &AsterixMessage) {
    // I048_010
    let attributes = &message.attributes_map;

    // I048_010
    let i048_010_octets = vec![0x19 as u8, 0xC9];
    _assert_eq_attribute_bitvec_value(&i048_010_octets, &attributes, "I048_010_sac", 16, 9);
    _assert_eq_attribute_bitvec_value(&i048_010_octets, &attributes, "I048_010_sic", 8, 1);

    // I048_020
    // todo: not sure about bit order, need to check and occasionaly change test code
    let i048_020_octets = vec![0xA0 as u8];
    _assert_eq_attribute_bitvec_value(&i048_020_octets, &attributes, "I048_020_typ", 8, 6);
    _assert_eq_attribute_bitvec_value(&i048_020_octets, &attributes, "I048_020_sim", 5, 5);
    _assert_eq_attribute_bitvec_value(&i048_020_octets, &attributes, "I048_020_rdp", 4, 4);
    _assert_eq_attribute_bitvec_value(&i048_020_octets, &attributes, "I048_020_spi", 3, 3);
    _assert_eq_attribute_bitvec_value(&i048_020_octets, &attributes, "I048_020_rab", 2, 2);

    // I048_140
    let i048_140_octets = vec![0x35 as u8, 0x6D, 0x4D];
    _assert_eq_attribute_bitvec_value(&i048_140_octets, &attributes, "I048_140_time_of_day", 24, 1);

    // I048_230
    let i048_230_octets = vec![0x20 as u8, 0xF5];
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_com", 16, 14);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_stat", 13, 11);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_si", 10, 10);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_mssc", 8, 8);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_mssc", 8, 8);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_arc", 7, 7);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_aic", 6, 6);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_b1a", 5, 5);
    _assert_eq_attribute_bitvec_value(&i048_230_octets, &attributes, "I048_230_b1b", 4, 1);

    // todo: check other attributes? Or an amostrage is good enough
}

fn _assert_eq_attribute_bitvec_value(octets: &Vec<u8>, attributes: &BTreeMap<String, Attribute>,attr_key: &str, msb_index: usize, lsb_index: usize) {
    let octets_bits = _get_expected_bits_from_u8_vec(octets);
    let expected_bits = get_bitvec_subset_as_msb0(&octets_bits, msb_index, lsb_index);
    let attribute = attributes.get(attr_key).unwrap(); 
    assert_eq!(expected_bits, attribute.bits, "{} bits should match", attr_key);
}

fn _get_expected_bits_from_u8_vec(vec_u8: &Vec<u8>) -> BitVec<u8, Msb0> {
    // let mut bitvec = (vec_u8).view_bits::<Msb0>().to_bitvec();
    let bitvec = get_msb_bits(vec_u8.as_slice());
    bitvec
}