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, TypeVariant, 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        write!(f, "\"")?;
114        format_utf8_slice(&self.0, f)?;
115        write!(f, "\"")?;
116
117        Ok(())
118    }
119}
120
121impl Display for RawByteStr {
122    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
123        write!(f, "\"")?;
124        format_utf8_slice(&self.0, f)?;
125        write!(f, "\"")?;
126
127        Ok(())
128    }
129}
130
131/* TypesPrinter */
132
133pub(crate) struct TypesPrinter<'a> {
134    types: &'a Types,
135}
136
137#[derive(Default)]
138struct State {
139    level: usize,
140    visit: HashSet<Ident>,
141}
142
143impl<'a> TypesPrinter<'a> {
144    pub(crate) fn new(types: &'a Types) -> Self {
145        Self { types }
146    }
147
148    fn print_all(&self, f: &mut Formatter<'_>, s: &mut State) -> FmtResult {
149        for (ident, ty) in &**self.types {
150            self.print_type(f, s, ident, ty)?;
151        }
152
153        Ok(())
154    }
155
156    fn resolve_complex_type(
157        &self,
158        f: &mut Formatter<'_>,
159        s: &mut State,
160        ident: &Ident,
161    ) -> FmtResult {
162        if let Some(x) = self.types.get(ident) {
163            self.print_type(f, s, ident, x)
164        } else {
165            writeln!(f, "NOT FOUND")?;
166
167            Ok(())
168        }
169    }
170
171    #[allow(clippy::too_many_lines)]
172    fn print_type(
173        &self,
174        f: &mut Formatter<'_>,
175        s: &mut State,
176        ident: &Ident,
177        ty: &Type,
178    ) -> FmtResult {
179        macro_rules! indent {
180            ($( $tt:tt )*) => {{
181                write!(f, "{0:1$}", "", 4 * s.level)?;
182                write!(f, $( $tt )*)?;
183            }};
184        }
185        macro_rules! indentln {
186            ($( $tt:tt )*) => {{
187                write!(f, "{0:1$}", "", 4 * s.level)?;
188                writeln!(f, $( $tt )*)?;
189            }};
190        }
191
192        if !s.visit.insert(ident.clone()) {
193            writeln!(f, "LOOP DETECTED ({})", ident.name)?;
194
195            return Ok(());
196        }
197
198        match &ty.variant {
199            TypeVariant::BuildIn(x) => {
200                writeln!(f, "{}: BuildIn", ident)?;
201
202                s.level += 1;
203
204                indentln!("display_name={:?}", &ty.display_name);
205                indentln!("type={x:?}");
206
207                s.level -= 1;
208            }
209            TypeVariant::Union(x) => {
210                writeln!(f, "{}: Union", ident)?;
211
212                s.level += 1;
213
214                indentln!("display_name={:?}", &ty.display_name);
215                indentln!("base={}", x.base);
216                indentln!("types");
217
218                s.level += 1;
219
220                for ty in &*x.types {
221                    indentln!("{}", &ty.type_);
222                }
223
224                s.level -= 2;
225            }
226            TypeVariant::Reference(x) => {
227                writeln!(f, "{}: Reference", ident)?;
228
229                s.level += 1;
230
231                indentln!("display_name={:?}", &ty.display_name);
232                indentln!("min={}", x.min_occurs);
233                indentln!("max={:?}", x.max_occurs);
234                indentln!("type={}", x.type_);
235
236                s.level -= 1;
237            }
238            TypeVariant::Dynamic(x) => {
239                writeln!(f, "{}: Dynamic", ident)?;
240
241                s.level += 1;
242
243                indentln!("display_name={:?}", &ty.display_name);
244                indentln!("types");
245
246                s.level += 1;
247
248                for ty in &*x.derived_types {
249                    indentln!("{}", ty);
250                }
251
252                s.level -= 2;
253            }
254            TypeVariant::Enumeration(x) => {
255                writeln!(f, "{}: Enumeration", ident)?;
256
257                s.level += 1;
258
259                indentln!("display_name={:?}", &ty.display_name);
260                indentln!("base={}", x.base);
261                indentln!("variants");
262
263                s.level += 1;
264
265                for var in &*x.variants {
266                    indentln!("{}={:?}", var.ident.name, var.use_);
267                }
268
269                s.level -= 2;
270            }
271            TypeVariant::All(x) | TypeVariant::Choice(x) | TypeVariant::Sequence(x) => {
272                match &ty.variant {
273                    TypeVariant::All(_) => writeln!(f, "{}: All", ident)?,
274                    TypeVariant::Choice(_) => writeln!(f, "{}: Choice", ident)?,
275                    TypeVariant::Sequence(_) => writeln!(f, "{}: Sequence", ident)?,
276                    _ => (),
277                }
278
279                s.level += 1;
280
281                indentln!("display_name={:?}", &ty.display_name);
282
283                if let Some(x) = &x.any {
284                    indentln!("any");
285
286                    s.level += 1;
287
288                    if let Some(x) = &x.min_occurs {
289                        indentln!("min_occurs={x:?}");
290                    }
291                    if let Some(x) = &x.max_occurs {
292                        indentln!("max_occurs={x:?}");
293                    }
294                    if let Some(x) = &x.namespace {
295                        indentln!("namespace={x:?}");
296                    }
297                    if let Some(x) = &x.not_namespace {
298                        indentln!("not_namespace={x:?}");
299                    }
300                    if let Some(x) = &x.not_q_name {
301                        indentln!("not_q_name={x:?}");
302                    }
303                    if let Some(x) = &x.process_contents {
304                        indentln!("process_contents={x:?}");
305                    }
306
307                    s.level -= 1;
308                }
309
310                for x in &*x.elements {
311                    indentln!("element");
312
313                    s.level += 1;
314
315                    indentln!("name={}", x.ident.name);
316                    indentln!("min_occurs={}", x.min_occurs);
317                    indentln!("max_occurs={:?}", x.max_occurs);
318                    indentln!("element_type={:?}", x.element_mode);
319
320                    if x.element_mode == ElementMode::Element {
321                        indentln!("type={}", x.type_);
322                    } else {
323                        indent!("type=");
324                        self.resolve_complex_type(f, s, &x.type_)?;
325                    }
326
327                    s.level -= 1;
328                }
329
330                s.level -= 1;
331            }
332            TypeVariant::ComplexType(x) => {
333                writeln!(f, "{}: ComplexType", ident)?;
334
335                s.level += 1;
336
337                indentln!("display_name={:?}", &ty.display_name);
338                indentln!("base={}", x.base);
339                indentln!("min_occurs={}", x.min_occurs);
340                indentln!("max_occurs={:?}", x.max_occurs);
341                indentln!("is_dynamic={}", x.is_dynamic);
342
343                if let Some(x) = &x.any_attribute {
344                    indentln!("any_attribute");
345
346                    s.level += 1;
347
348                    if let Some(x) = &x.namespace {
349                        indentln!("namespace={x:?}");
350                    }
351                    if let Some(x) = &x.not_namespace {
352                        indentln!("not_namespace={x:?}");
353                    }
354                    if let Some(x) = &x.not_q_name {
355                        indentln!("not_q_name={x:?}");
356                    }
357                    if let Some(x) = &x.process_contents {
358                        indentln!("process_contents={x:?}");
359                    }
360
361                    s.level -= 1;
362                }
363
364                for x in &*x.attributes {
365                    indentln!("attribute");
366
367                    s.level += 1;
368
369                    indentln!("name={}", x.ident.name);
370                    indentln!("type={}", x.type_);
371                    indentln!("use={:?}", x.use_);
372                    indentln!("default={:?}", x.default);
373
374                    s.level -= 1;
375                }
376
377                if let Some(content) = &x.content {
378                    indentln!("content");
379
380                    s.level += 1;
381
382                    indent!("type=");
383                    self.resolve_complex_type(f, s, content)?;
384
385                    s.level -= 1;
386                }
387
388                s.level -= 1;
389            }
390        }
391
392        s.visit.remove(ident);
393
394        Ok(())
395    }
396}
397
398impl Display for TypesPrinter<'_> {
399    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
400        let mut s = State::default();
401
402        self.print_all(f, &mut s)
403    }
404}
405
406/* Helper */
407
408pub(crate) fn format_utf8_slice(bytes: &[u8], f: &mut Formatter<'_>) -> FmtResult {
409    for byte in bytes {
410        if byte.is_ascii_control() {
411            write!(f, r"\x{byte:02x}")?;
412        } else {
413            write!(f, "{}", *byte as char)?;
414        }
415    }
416
417    Ok(())
418}