asterix_parser 0.1.1

Playground do Protocolo ASTERIX
Documentation
use std::fs::OpenOptions;
use std::io::Read;

use asterix_parser::asterix::uap_json::enums::{AttributeItem, AttributeType, AttributeValueType, ConstraintType, DataItemType, DataItemValueType, DataType, DenominatorType, ElementType, ElementValueType, LsbType};
use asterix_parser::asterix::uap_json::structures::{AttributeRule, ConstraintRule, DataItemRule, DataRecord};

#[test]
pub(crate) fn test_read_asterix_json_spec_from_file() {
    let _cat034_1_29_file_path = "resources/uaps/cat034_1_29_definition.json";
    let _cat048_1_30_file_path = "resources/uaps/cat048_1_30_definition.json";
    let _cat048_1_31_file_path = "resources/uaps/cat048_1_31_definition.json";
    let mut myfile = match OpenOptions::new()
    .read(true)
    .write(false)
    .create(false)
    .open(_cat048_1_31_file_path) {
        Ok(f) => f,
        Err(e) => panic!("Error opening file {}", e),
    };

    let mut raw_json = String::new();
    myfile.read_to_string(&mut raw_json).unwrap();

    let trimmed_json = raw_json.trim();
    let deserialized:DataRecord  = match serde_json::from_str(&trimmed_json) {
        Ok(d) => d,
        Err(e) => {
            panic!("Error message: {}", e.to_string())
        },
    };

    println!("Category: {:03}, {}, edition: {}.{}", 
        deserialized.number, 
        deserialized.title, 
        deserialized.edition.major,
        deserialized.edition.minor);
        println!();
    for dataitem in &deserialized.catalogue {
        // let rule = &content.rule;
        println!("DataItem: {}, {}", dataitem.name, dataitem.title);
        let describe = true;
        if describe {
            if dataitem.name == "030" {
                let description = describe_data_item(dataitem);
                println!("{}", description)
            }
        }
    }
}

fn describe_data_item(dataitem: &DataItemRule) -> String {
    let mut description: Vec<String> = vec![format!("Dataitem: {}, {}", dataitem.name, dataitem.title)];
    let rule_desc: String;
    match &dataitem.rule {
        DataItemType::ContextFree { value } => {
            rule_desc = match value {
                DataItemValueType::Element { rule, size} => describe_element(rule, size),
                DataItemValueType::Group { items } => describe_option_attribute_item(&items),
                DataItemValueType::Extended { items } => describe_option_attribute_item(&items),
                DataItemValueType::Repetitive { rep, variation }
                    => describe_repetitive(rep, &variation),
                DataItemValueType::Compound { fspec, items } 
                    => describe_compound(&fspec, &items),
                DataItemValueType::Explicit { expl } => format!("Explicit: {}", expl)
            };
        },
    };
    description.push(rule_desc);
    
    description.join("\n")
}

fn describe_option_attribute_item(items: &Vec<Option<AttributeItem>>) -> String {
    let mut description = vec![String::from("Attributes: "), ];
    for attribute_item in items {
        let attribute_description =   match attribute_item {
            Some(a) => { describe_attribute_item(a) }
            None => continue
        };

        description.push(attribute_description);
    }

    description.join("\n")
}

fn describe_attribute_item(attribute_item: &AttributeItem) -> String {
    let description = match attribute_item {
        AttributeItem::SpareEntry { length, spare } => {
            if *spare
            {
                format!("Spare entry: length:{}", length)
            }
            else {
                String::new()
            }
        },
        AttributeItem::AttributeEntry(e) => describe_attribute_entry(e)
    };

    description
}

fn describe_attribute_entry(attribute_rule: &AttributeRule) -> String {
    let mut description = format!("Attributo {} - {}", attribute_rule.name, attribute_rule.title);

    let mut _rule: String; 
    match &attribute_rule.rule {
        AttributeType::ContextFree { value } => { _rule = describe_attribute_value_type(value);},
    };

    description.push_str(_rule.as_str());

    description
}

fn describe_attribute_value_type(attribute_value_type: &AttributeValueType) -> String {
    let attribute_value_type_desc = match attribute_value_type {
        AttributeValueType::Element { rule, size } => describe_element(rule, &size),
        AttributeValueType::Group { items } => describe_group(items),
        AttributeValueType::Table { values } => describe_table(&values),
        AttributeValueType::Repetitive { rep, variation } => describe_repetitive(rep, &variation),
    };      

    attribute_value_type_desc
}

fn describe_element(element_rule: &ElementType, size: &u8) -> String {
    let mut description: Vec<String> = vec![String::from("Element Type: ")]; 
    match element_rule {
        ElementType::ContextFree { value } =>  {
            let element_desc = describe_element_type(value);
            description.push(element_desc);     
        }
    };
    description.push(format!("Size: {}", size));
    description.join("\n")
}

fn describe_element_type(value: &ElementValueType) -> String {
    let element_desc = match value {
        ElementValueType::Fx => format!("{}", "Fx"),
        ElementValueType::Integer { 
            constraints, 
            signed 
            } => describe_integer(constraints, signed),
        ElementValueType::Raw => format!("{}", "Raw"),
        ElementValueType::Regular { size } => format!("{}:{:?}", "Regular", size),
        /* ElementValueType::Group { items } => {
            let mut items_desc: Vec<String> = vec![];
            for item in items{
                items_desc.push(describe_attribute_entry(&item))
            }
            items_desc.join("\n")
        }, */
        ElementValueType::Quantity { 
            constraints, 
            lsb, 
            signed, 
            unit } => {
                describe_quantity(constraints, lsb, signed, unit)
            },
        ElementValueType::String { variation } => format!("{}:{}", "String", variation),
        ElementValueType::Table { values } =>  describe_table(values),
    }; 

    element_desc
}

fn describe_quantity(constraints: &[ConstraintRule], lsb: &LsbType, signed: &bool, unit: &str) -> String {
    let mut quantity_desc: Vec<String> = vec![String::from("Quantity: ")];
    if constraints.len() > 0 {
        quantity_desc.push(String::from("Constraint(s): "))
    }
    for constraint in constraints {
        let mut constraint_desc: String = match constraint.constraint_type {
            ConstraintType::Less => format!("constraint, type: {}", "Less"),
            ConstraintType::Great => format!("constraint, type: {}", "Great"),
            ConstraintType::LessOrEqual => format!("constraint, type: {}", "LessOrEqual"),
            ConstraintType::GreatOrEqual => format!("constraint, type: {}", "GreatOrEqual"),
        };
        let constraint_value: String = match constraint.value {
            DataType::Integer { value } => format!(", value: {}", value),
        };
        constraint_desc.push_str(constraint_value.as_str());
        quantity_desc.push(constraint_desc);
    }
    
    let lsb_desc = match lsb {
        LsbType::Integer { value } => format!("Lsb type Integer: {}", value),
        LsbType::Div { denominator, numerator } => {
            let denomminator = match denominator {
                DenominatorType::Pow { base, exponent } => format!("Denom base {}, exponent {}", base, exponent),
            };
            let numerator = match numerator {
                DataType::Integer { value } => format!("Num {}", value),
            };
            format!("Lsb type Div, denominator {}, numerator {}", denomminator, numerator)
        }
    };
    quantity_desc.push(lsb_desc);
    quantity_desc.push(format!("Signed: {}", signed));
    quantity_desc.push(format!("Unit: {}", unit));

    quantity_desc.join("\n")
}

fn describe_integer(constraints: &[ConstraintRule], signed: &bool) -> String {
    let mut integer_desc: Vec<String> = vec![String::from("Integer: ")];
    if constraints.len() > 0 {
        integer_desc.push(String::from("Constraint(s): "))
    }
    for constraint in constraints {
            let mut constraint_desc: String = match constraint.constraint_type {
                ConstraintType::Less => format!("constraint, type: {}", "Less"),
                ConstraintType::Great => format!("constraint, type: {}", "Great"),
                ConstraintType::LessOrEqual => format!("constraint, type: {}", "LessOrEqual"),
                ConstraintType::GreatOrEqual => format!("constraint, type: {}", "GreatOrEqual"),
            };
            let constraint_value: String = match constraint.value {
                DataType::Integer { value } => format!(", value: {}", value),
            };
            constraint_desc.push_str(constraint_value.as_str());
            integer_desc.push(constraint_desc);
    }
    
    if *signed {
        integer_desc.push("Signed: {}".to_owned());
    }

    integer_desc.join("\n")
}

fn describe_group(items: &Vec<Option<AttributeItem>>) -> String {
    let mut description = vec!["Attributes: ".to_owned()];
    for item in items {
        match item {
            Some(e) => { description.push(describe_attribute_item(e)); },
            None => ()
        }
    }
    description.join("\n")
}

fn describe_table(values: &Vec<(i32, String)>) -> String {
    let mut description = vec!["Table values: ".to_owned()];

    for item in values {
        description.push(format!("{}:{}", item.0, item.1));
    }
    
    description.join("\n")
}

fn describe_compound(fspec: &Option<u8>, items: &Vec<Option<AttributeItem>>) -> String {
    let mut description = vec!["Compound: ".to_owned()];
    match fspec {
        Some(v) => { description.push(format!("fspec: {:?}", v)); },
        None => (),
    }

    for item in items {
        let attribute_item = match item {
            Some(a) => a,
            None => continue,
        };
        let attribute_desc = match attribute_item {
            AttributeItem::SpareEntry { length, spare } => {
                if *spare
                {
                    format!("Spare entry: length:{}", length)
                }
                else {
                    String::new()
                }
            },
            AttributeItem::AttributeEntry(e) => describe_attribute_entry(&e),
        };
        
        description.push(attribute_desc);
    }

    description.join("\n")
}

fn describe_repetitive(rep: &ElementValueType, variation: &AttributeValueType) -> String {
    let mut description = vec!["Repetitive: ".to_owned()];
    let rep_desc = describe_element_type(rep); 
    description.push(format!("rep: {}", rep_desc));
    let attribute_type_desc = describe_attribute_value_type(variation);
    description.push(format!("variation: {}", attribute_type_desc));

    description.join("\n")
}