catalogue/
lib.rs

1use camino::Utf8Path;
2use parse::{
3    xml,
4    UpperName,
5};
6use parse::xml::*;
7use roxmltree::{
8    Node,
9};
10use std::collections::BTreeMap;
11
12mod classification;
13mod error;
14
15pub use classification::{
16    Classification,
17    ClassificationFolder,
18    ClassificationId,
19};
20pub use error::Error;
21
22pub struct Catalogue {
23    pub classifications: BTreeMap<UpperName, Classification>,
24}
25
26pub fn parse<P: AsRef<Utf8Path>>(path: P)
27    -> Result<Catalogue, ParseErrors<Error>>
28{
29	xml::parse(path, Catalogue::parse)
30}
31
32impl Catalogue {
33    fn parse(
34        element: Node,
35        errors: &mut Vec<Error>,
36    ) -> Option<Self> {
37        let mut classifications = ParsingMap::new();
38        let mut limits = Vec::new();
39
40        for child in element.children() {
41            let Some(name) = element_name(&child, errors) else {
42                continue;
43            };
44
45            match name {
46                "classification" =>
47                     Classification::parse(&mut classifications, &mut limits, child, errors),
48
49                _ =>
50                    unexpected_element(child, errors),
51            }
52        }
53
54        let Some(mut classifications) = classifications.collect_to_btree() else {
55            return None;
56        };
57
58        let mut failure = false;
59
60        for limit in limits {
61            if let Some(national) = classifications.get_mut(&limit.national) {
62                national.has_national_limit = Some(limit.limit);
63            } else {
64                errors.push(Error::NationalNotFound {
65                    range: limit.range.into(),
66
67                    national: limit.national.into(),
68                });
69
70                failure = true;
71            }
72        }
73
74        if failure {
75            return None;
76        }
77
78        Some(Catalogue {
79            classifications,
80        })
81    }
82}