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}