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 = 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>) -> 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 = 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 = 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 = 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 = 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>) -> 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, items: &Vec>) -> 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") }