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