libxml/
error.rs

1//!
2//! Wrapper for xmlError
3//!
4use super::bindings;
5
6use std::ffi::{c_char, c_int, CStr};
7
8/// Rust enum variant of libxml2's xmlErrorLevel
9#[derive(Debug)]
10pub enum XmlErrorLevel {
11  /// No error
12  None,
13  /// A simple warning
14  Warning,
15  /// A recoverable error
16  Error,
17  /// A fatal error
18  Fatal,
19}
20
21impl XmlErrorLevel {
22  /// Convert an xmlErrorLevel provided by libxml2 (as an integer) into a Rust enum
23  pub fn from_raw(error_level: bindings::xmlErrorLevel) -> XmlErrorLevel {
24    match error_level {
25      bindings::xmlErrorLevel_XML_ERR_NONE => XmlErrorLevel::None,
26      bindings::xmlErrorLevel_XML_ERR_WARNING => XmlErrorLevel::Warning,
27      bindings::xmlErrorLevel_XML_ERR_ERROR => XmlErrorLevel::Error,
28      bindings::xmlErrorLevel_XML_ERR_FATAL => XmlErrorLevel::Fatal,
29      _ => unreachable!("Should never receive an error level not in the range 0..=3"),
30    }
31  }
32}
33
34/// Wrapper around xmlErrorPtr.
35/// Some fields have been omitted for simplicity/safety
36#[derive(Debug)]
37pub struct StructuredError {
38  /// Human-friendly error message, lossily converted into UTF-8 from the underlying
39  /// C string. May be `None` if an error message is not provided by libxml2.
40  pub message: Option<String>,
41  /// The error's level
42  pub level: XmlErrorLevel,
43  /// The filename, lossily converted into UTF-8 from the underlying C string.
44  /// May be `None` if a filename is not provided by libxml2, such as when validating
45  /// an XML document stored entirely in memory.
46  pub filename: Option<String>,
47  /// The linenumber, or None if not applicable.
48  pub line: Option<c_int>,
49  /// The column where the error is present, or None if not applicable.
50  pub col: Option<c_int>,
51
52  /// The module that the error came from. See libxml's xmlErrorDomain enum.
53  pub domain: c_int,
54  /// The variety of error. See libxml's xmlParserErrors enum.
55  pub code: c_int,
56}
57
58impl StructuredError {
59  /// Copies the error information stored at `error_ptr` into a new `StructuredError`
60  /// 
61  /// # Safety
62  /// This function must be given a pointer to a valid `xmlError` struct. Typically, you
63  /// will acquire such a pointer by implementing one of a number of callbacks
64  /// defined in libXml which are provided an `xmlError` as an argument.
65  /// 
66  /// This function copies data from the memory `error_ptr` but does not deallocate
67  /// the error. Depending on the context in which this function is used, you may
68  /// need to take additional steps to avoid a memory leak.
69  pub unsafe fn from_raw(error_ptr: *const bindings::xmlError) -> Self {
70    let error = *error_ptr;
71    let message = StructuredError::ptr_to_string(error.message);
72    let level = XmlErrorLevel::from_raw(error.level);
73    let filename = StructuredError::ptr_to_string(error.file);
74
75    let line = if error.line == 0 {
76      None
77    } else {
78      Some(error.line)
79    };
80    let col = if error.int2 == 0 {
81      None
82    } else {
83      Some(error.int2)
84    };
85
86    StructuredError {
87      message,
88      level,
89      filename,
90      line,
91      col,
92      domain: error.domain,
93      code: error.code,
94    }
95  }
96
97  /// Human-readable informative error message.
98  /// 
99  /// This function is a hold-over from the original bindings to libxml's error
100  /// reporting mechanism. Instead of calling this method, you can access the 
101  /// StructuredError `message` field directly.
102  #[deprecated(since="0.3.3", note="Please use the `message` field directly instead.")]
103  pub fn message(&self) -> &str {
104    self.message.as_deref().unwrap_or("")
105  }
106
107  /// Returns the provided c_str as Some(String), or None if the provided pointer is null.
108  fn ptr_to_string(c_str: *mut c_char) -> Option<String> {
109    if c_str.is_null() {
110      return None;
111    }
112
113    let raw_str = unsafe { CStr::from_ptr(c_str) };
114    Some(String::from_utf8_lossy(raw_str.to_bytes()).to_string())
115  }
116}