parse/
xml.rs

1use camino::{
2    Utf8Path,
3};
4use roxmltree::{
5    Document,
6    Node,
7};
8use std::ops::Range;
9use std::marker::PhantomData;
10
11mod attribute;
12mod element;
13pub mod error;
14mod map;
15mod once;
16
17pub use attribute::*;
18pub use element::*;
19pub use error::{
20    ParseError,
21    ParseErrors,
22};
23pub use map::*;
24pub use once::Once;
25
26pub trait Id: Clone {
27    fn zero() -> Self;
28    fn succ(&mut self);
29    fn index(&self) -> usize;
30}
31
32pub fn parse<P, T, E, W>(path: P, with: W) -> Result<T, ParseErrors<E>>
33where
34    P: AsRef<Utf8Path>,
35    E: miette::Diagnostic,
36    W: FnOnce(Node, &mut Vec<E>) -> Option<T>,
37{
38    let path = path.as_ref();
39    let source = match std::fs::read_to_string(path) {
40        Ok(source) => source,
41        Err(error) =>
42            return Err(ParseErrors::open(error, path)),
43    };
44    let document: Document = match Document::parse(&source) {
45        Ok(document) => document,
46        Err(error) =>
47            return Err(ParseErrors::xml(error, path, source)),
48    };
49
50    let mut errors = Vec::new();
51
52    if let Some(t) = with(document.root_element(), &mut errors) {
53        if errors.is_empty() {
54            Ok(t)
55        } else {
56            Err(ParseErrors::parse(path, source, errors))
57        }
58    } else {
59        Err(ParseErrors::parse(path, source, errors))
60    }
61}
62
63#[derive(Clone)]
64pub struct Parsed<T> {
65    pub range: Range<usize>,
66    pub value: T,
67}
68
69pub struct Marker<E> {
70    error_count: usize,
71    phantom: PhantomData<E>
72}
73
74impl<E> Clone for Marker<E> {
75    fn clone(&self) -> Self {
76        Marker {
77            error_count: self.error_count,
78            phantom: PhantomData,
79        }
80    }
81}
82
83pub trait Errors<E> {
84    fn marker(&self) -> Marker<E>;
85    fn since(&self, marker: Marker<E>) -> bool;
86}
87
88impl<E> Errors<E> for Vec<E> {
89    fn marker(&self) -> Marker<E> {
90        Marker {
91            error_count: self.len(),
92            phantom: PhantomData,
93        }
94    }
95
96    fn since(&self, marker: Marker<E>) -> bool {
97        self.len() > marker.error_count
98    }
99}
100