xsd_parser/
misc.rs

1use std::borrow::Cow;
2use std::collections::HashSet;
3use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
4use std::io::Error as IoError;
5
6use anyhow::Error as AnyError;
7use thiserror::Error;
8
9use crate::types::{ElementMode, Ident, Type, Types};
10use crate::{GeneratorError, InterpreterError, ParserError};
11
12/// Trait that adds namespace information to a type.
13pub trait WithNamespace {
14    /// The default namespace prefix for this type.
15    fn prefix() -> Option<&'static str>;
16
17    /// The namespace for this type.
18    fn namespace() -> Option<&'static str>;
19}
20
21/// Trait that is used to get the [`Any`](core::any::Any) trait for a specific type.
22pub trait AsAny: core::any::Any {
23    /// Get a reference to the current object as [`Any`](core::any::Any).
24    fn as_any(&self) -> &dyn core::any::Any;
25
26    /// Get a mutable reference to the current object as [`Any`](core::any::Any).
27    fn as_any_mut(&mut self) -> &mut dyn core::any::Any;
28}
29
30impl<X: 'static> AsAny for X {
31    fn as_any(&self) -> &dyn core::any::Any {
32        self
33    }
34
35    fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
36        self
37    }
38}
39
40/// Error emitted by the [`generate`](crate::generate) function.
41#[derive(Debug, Error)]
42pub enum Error {
43    /// IO Error.
44    #[error("IO Error: {0}")]
45    IoError(#[from] IoError),
46
47    /// Parser error.
48    #[error("Parser error: {0}")]
49    ParserError(ParserError<AnyError>),
50
51    /// Interpreter error.
52    #[error("Interpreter error: {0}")]
53    InterpreterError(#[from] InterpreterError),
54
55    /// Generator error.
56    #[error("Generator error: {0}")]
57    GeneratorError(#[from] GeneratorError),
58}
59
60impl<E> From<ParserError<E>> for Error
61where
62    AnyError: From<E>,
63{
64    fn from(value: ParserError<E>) -> Self {
65        match value {
66            ParserError::IoError(err) => Self::ParserError(ParserError::IoError(err)),
67            ParserError::XmlError(err) => Self::ParserError(ParserError::XmlError(err)),
68            ParserError::UrlParseError(err) => Self::ParserError(ParserError::UrlParseError(err)),
69            ParserError::UnableToResolve(url) => {
70                Self::ParserError(ParserError::UnableToResolve(url))
71            }
72            ParserError::Resolver(err) => {
73                Self::ParserError(ParserError::Resolver(AnyError::from(err)))
74            }
75            ParserError::InvalidFilePath(path) => {
76                Self::ParserError(ParserError::InvalidFilePath(path))
77            }
78        }
79    }
80}
81
82/// Helper type that implements [`Debug`] and [`Display`] for a byte slice.
83pub struct RawByteStr(Cow<'static, [u8]>);
84
85impl RawByteStr {
86    /// Create a new [`RawByteStr`] instance from the passed byte slice.
87    #[must_use]
88    pub fn from_slice(value: &[u8]) -> Self {
89        Self(Cow::Owned(value.to_owned()))
90    }
91}
92
93impl From<Vec<u8>> for RawByteStr {
94    fn from(value: Vec<u8>) -> Self {
95        Self(Cow::Owned(value))
96    }
97}
98
99impl From<&'static [u8]> for RawByteStr {
100    fn from(value: &'static [u8]) -> Self {
101        Self(Cow::Borrowed(value))
102    }
103}
104
105impl From<&'static str> for RawByteStr {
106    fn from(value: &'static str) -> Self {
107        Self(Cow::Borrowed(value.as_bytes()))
108    }
109}
110
111impl Debug for RawByteStr {
112    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
113        format_utf8_slice(&self.0, f)
114    }
115}
116
117impl Display for RawByteStr {
118    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
119        format_utf8_slice(&self.0, f)
120    }
121}
122
123/* TypesPrinter */
124
125pub(crate) struct TypesPrinter<'a> {
126    types: &'a Types,
127}
128
129#[derive(Default)]
130struct State {
131    level: usize,
132    visit: HashSet<Ident>,
133}
134
135impl<'a> TypesPrinter<'a> {
136    pub(crate) fn new(types: &'a Types) -> Self {
137        Self { types }
138    }
139
140    fn print_all(&self, f: &mut Formatter<'_>, s: &mut State) -> FmtResult {
141        for (ident, ty) in &**self.types {
142            self.print_type(f, s, ident, ty)?;
143        }
144
145        Ok(())
146    }
147
148    fn resolve_complex_type(
149        &self,
150        f: &mut Formatter<'_>,
151        s: &mut State,
152        ident: &Ident,
153    ) -> FmtResult {
154        if let Some(x) = self.types.get(ident) {
155            self.print_type(f, s, ident, x)
156        } else {
157            writeln!(f, "NOT FOUND")?;
158
159            Ok(())
160        }
161    }
162
163    #[allow(clippy::too_many_lines)]
164    fn print_type(
165        &self,
166        f: &mut Formatter<'_>,
167        s: &mut State,
168        ident: &Ident,
169        ty: &Type,
170    ) -> FmtResult {
171        macro_rules! indent {
172            ($( $tt:tt )*) => {{
173                write!(f, "{0:1$}", "", 4 * s.level)?;
174                write!(f, $( $tt )*)?;
175            }};
176        }
177        macro_rules! indentln {
178            ($( $tt:tt )*) => {{
179                write!(f, "{0:1$}", "", 4 * s.level)?;
180                writeln!(f, $( $tt )*)?;
181            }};
182        }
183
184        if !s.visit.insert(ident.clone()) {
185            writeln!(f, "LOOP DETECTED ({})", ident.name)?;
186
187            return Ok(());
188        }
189
190        match ty {
191            Type::BuildIn(x) => {
192                writeln!(f, "{}: BuildIn", ident)?;
193
194                s.level += 1;
195
196                indentln!("type={x:?}");
197
198                s.level -= 1;
199            }
200            Type::Union(x) => {
201                writeln!(f, "{}: Union", ident)?;
202
203                s.level += 1;
204
205                indentln!("base={}", x.base);
206                indentln!("types");
207
208                s.level += 1;
209
210                for ty in &*x.types {
211                    indentln!("{}", &ty.type_);
212                }
213
214                s.level -= 2;
215            }
216            Type::Reference(x) => {
217                writeln!(f, "{}: Reference", ident)?;
218
219                s.level += 1;
220
221                indentln!("min={}", x.min_occurs);
222                indentln!("max={:?}", x.max_occurs);
223                indentln!("type={}", x.type_);
224
225                s.level -= 1;
226            }
227            Type::Dynamic(x) => {
228                writeln!(f, "{}: Dynamic", ident)?;
229
230                s.level += 1;
231
232                indentln!("types");
233
234                s.level += 1;
235
236                for ty in &*x.derived_types {
237                    indentln!("{}", ty);
238                }
239
240                s.level -= 2;
241            }
242            Type::Enumeration(x) => {
243                writeln!(f, "{}: Enumeration", ident)?;
244
245                s.level += 1;
246
247                indentln!("base={}", x.base);
248                indentln!("variants");
249
250                s.level += 1;
251
252                for var in &*x.variants {
253                    indentln!("{}={:?}", var.ident.name, var.use_);
254                }
255
256                s.level -= 2;
257            }
258            Type::All(x) | Type::Choice(x) | Type::Sequence(x) => {
259                match ty {
260                    Type::All(_) => writeln!(f, "{}: All", ident)?,
261                    Type::Choice(_) => writeln!(f, "{}: Choice", ident)?,
262                    Type::Sequence(_) => writeln!(f, "{}: Sequence", ident)?,
263                    _ => (),
264                }
265
266                s.level += 1;
267
268                if let Some(x) = &x.any {
269                    indentln!("any");
270
271                    s.level += 1;
272
273                    if let Some(x) = &x.min_occurs {
274                        indentln!("min_occurs={x:?}");
275                    }
276                    if let Some(x) = &x.max_occurs {
277                        indentln!("max_occurs={x:?}");
278                    }
279                    if let Some(x) = &x.namespace {
280                        indentln!("namespace={x:?}");
281                    }
282                    if let Some(x) = &x.not_namespace {
283                        indentln!("not_namespace={x:?}");
284                    }
285                    if let Some(x) = &x.not_q_name {
286                        indentln!("not_q_name={x:?}");
287                    }
288                    if let Some(x) = &x.process_contents {
289                        indentln!("process_contents={x:?}");
290                    }
291
292                    s.level -= 1;
293                }
294
295                for x in &*x.elements {
296                    indentln!("element");
297
298                    s.level += 1;
299
300                    indentln!("name={}", x.ident.name);
301                    indentln!("min_occurs={}", x.min_occurs);
302                    indentln!("max_occurs={:?}", x.max_occurs);
303                    indentln!("element_type={:?}", x.element_mode);
304
305                    if x.element_mode == ElementMode::Element {
306                        indentln!("type={}", x.type_);
307                    } else {
308                        indent!("type=");
309                        self.resolve_complex_type(f, s, &x.type_)?;
310                    }
311
312                    s.level -= 1;
313                }
314
315                s.level -= 1;
316            }
317            Type::ComplexType(x) => {
318                writeln!(f, "{}: ComplexType", ident)?;
319
320                s.level += 1;
321
322                indentln!("base={}", x.base);
323                indentln!("min_occurs={}", x.min_occurs);
324                indentln!("max_occurs={:?}", x.max_occurs);
325                indentln!("is_dynamic={}", x.is_dynamic);
326
327                if let Some(x) = &x.any_attribute {
328                    indentln!("any_attribute");
329
330                    s.level += 1;
331
332                    if let Some(x) = &x.namespace {
333                        indentln!("namespace={x:?}");
334                    }
335                    if let Some(x) = &x.not_namespace {
336                        indentln!("not_namespace={x:?}");
337                    }
338                    if let Some(x) = &x.not_q_name {
339                        indentln!("not_q_name={x:?}");
340                    }
341                    if let Some(x) = &x.process_contents {
342                        indentln!("process_contents={x:?}");
343                    }
344
345                    s.level -= 1;
346                }
347
348                for x in &*x.attributes {
349                    indentln!("attribute");
350
351                    s.level += 1;
352
353                    indentln!("name={}", x.ident.name);
354                    indentln!("type={}", x.type_);
355                    indentln!("use={:?}", x.use_);
356                    indentln!("default={:?}", x.default);
357
358                    s.level -= 1;
359                }
360
361                if let Some(content) = &x.content {
362                    indentln!("content");
363
364                    s.level += 1;
365
366                    indent!("type=");
367                    self.resolve_complex_type(f, s, content)?;
368
369                    s.level -= 1;
370                }
371
372                s.level -= 1;
373            }
374        }
375
376        s.visit.remove(ident);
377
378        Ok(())
379    }
380}
381
382impl Display for TypesPrinter<'_> {
383    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
384        let mut s = State::default();
385
386        self.print_all(f, &mut s)
387    }
388}
389
390/* Helper */
391
392pub(crate) fn format_utf8_slice(bytes: &[u8], f: &mut Formatter<'_>) -> FmtResult {
393    for byte in bytes {
394        if byte.is_ascii_control() {
395            write!(f, r"\x{byte:02x}")?;
396        } else {
397            write!(f, "{}", *byte as char)?;
398        }
399    }
400
401    Ok(())
402}