asterix_parser/
asterix.rs

1pub mod category;
2pub mod message;
3pub mod uap;
4pub mod uap_json;
5
6use std::collections::BTreeMap;
7use std::fs;
8use thiserror::Error;
9
10use self::category::{Category, CategoryIndex, CategoryKey};
11use self::uap::providers::Provider;
12use self::uap_json::errors::ParseError;
13use self::uap_json::loader::Loader;
14use self::uap_json::structures::{DataRecord, Edition};
15
16#[derive(Error, Debug)]
17pub enum ContextErrors {
18    #[error("Definition folder for UAPs could not be loaded")]
19    UAPDefinitionFolderCouldNotBeLoaded,
20    #[error("unknown error")]
21    Unknown,
22}
23
24/// A data block is blocking mechanism may be used to combine several Data Records in an ASTERIX Data Block.
25/// 
26/// An ASTERIX Data Block shall consist of:
27///     • a one-octet Data [Category] (CAT) field, indicating the ASTERIX Category;
28///     • a two-octet Length Indicator (LEN) field, indicating the total length (in octets) of the ASTERIX
29///       Data Block, including the CAT and LEN fields;
30/// 
31/// Each [Data Record](DataRecord) is of variable length but aligned on an octet boundary.
32/// The length of an ASTERIX Data Block is thus variable but shall always be a multiple of an octet.
33/// The maximum size of an ASTERIX Data Block shall be mutually agreed between data sources and
34/// users. Because of the size of the Length Indicator the maximum possible length of an ASTERIX Data
35/// Block is 65.535 octets.
36/// (from document:  [EUROCONTROL-SPEC-0149](https://www.eurocontrol.int/asterix))
37/// 
38pub struct DataBlock {
39    pub records: Vec<DataRecord>
40}
41
42type CategoryMap = BTreeMap<CategoryKey, Category>;
43type UapMap = BTreeMap<CategoryKey, DataRecord>;
44
45pub struct Context {
46    // pub uap_definitions: UAPDefinitions,
47    pub categories: CategoryMap,
48    pub uap_definitions: UapMap
49}
50
51impl Context {
52    const UAPS_FOLDER: &'static str = "./resources/uaps";
53
54    pub fn new() -> anyhow::Result<Context> {
55        let (categories, uap_defs) = Context::load()?;
56
57        Ok(Context { 
58            categories: categories,
59            uap_definitions: uap_defs
60        })
61    }
62
63    fn find_uap_definition_files() -> anyhow::Result<Vec<String>> {
64        let uap_files = match fs::read_dir(Context::UAPS_FOLDER) {
65            Ok(read_dir) => {
66                let mut files = Vec::<String>::new();
67                for result in read_dir {
68                    let path = match result {
69                        Ok(dir_entry) =>  {
70                            let filename = 
71                                match dir_entry.file_name().into_string() {
72                                    Ok(s) => s,
73                                    Err(_) => { return Err(ContextErrors::UAPDefinitionFolderCouldNotBeLoaded.into()); },
74                                };
75                            
76                            filename
77                        },
78                        Err(e) => { return Err(e.into()); },
79                    };
80                    files.push(path);
81                };
82                files
83            },
84            Err(e) => { return Err(e.into()); },
85        };
86        
87        /* for file in &uap_files {
88            println!("Loading file {}", file);
89        } */
90    
91        Ok(uap_files)
92    }
93    
94    fn load() -> anyhow::Result<(CategoryMap, UapMap)> {
95        let mut categories = CategoryMap::new();
96        let mut uap_defs = UapMap::new();
97
98        let uap_files = Context::find_uap_definition_files()?;
99        for file in uap_files {
100            let filepath_and_name = format!("{}/{}", Context::UAPS_FOLDER, file);
101            let uap_definition = Loader::load(&filepath_and_name)?;
102            let category_index = 
103                match CategoryIndex::from_u8(uap_definition.number) {
104                    Some(i) => i,
105                    None => { return Err(ParseError::OpenUapJsonDefinitionError.into()) }
106                };
107           
108            let category = 
109                Category::new(
110                    CategoryKey {
111                        index: category_index, 
112                        edition: uap_definition.edition.clone(),
113                        provider: Provider::Standard
114                    },
115                    uap_definition.title.as_str());
116
117            categories.insert(category.key.clone(), category.clone());
118            uap_defs.insert(category.key, uap_definition);
119        }
120
121        Ok((categories, uap_defs))
122    }    
123
124    pub fn find_definition(&self, category_key: CategoryKey) -> anyhow::Result<DataRecord> {
125        let mut uap_def_opt: Option<DataRecord> = None;
126
127        for uap in &self.uap_definitions {
128            if uap.0 == &category_key {
129                uap_def_opt = Some(uap.1.clone())
130            }
131        }
132
133        if uap_def_opt.is_none() {
134            return Err(ParseError::CategoryNotYetSupported { 
135                category_code: format!("{}", category_key.index.as_string()),
136                edition: format!("{}.{}", category_key.edition.major, category_key.edition.minor),
137                provider: category_key.provider.as_ref().to_owned(),
138             }.into());
139        }
140
141        Ok(uap_def_opt.unwrap())
142   }
143   
144    fn find_newest_edition_for_category(&self, cat_idx: &CategoryIndex) -> anyhow::Result<Edition> {
145        let uap_defs:&Vec<&CategoryKey> = &self.uap_definitions
146            .keys()
147                .into_iter()
148                    .filter(|x| x.index == *cat_idx).collect::<Vec<&CategoryKey>>();
149
150        if uap_defs.is_empty() {
151            return Err(ParseError::CategoryUapDefinitionNotFound { category_code: cat_idx.as_string()}.into());
152        }
153
154        let uap_def = *uap_defs.into_iter().max().unwrap();
155
156        Ok(uap_def.edition.clone())
157    }
158
159
160}
161