libxml/schemas/
parser.rs

1//!
2//! Wrapping of the Parser Context (xmlSchemaParserCtxt)
3//!
4use super::common;
5
6use crate::bindings;
7use crate::error::StructuredError;
8use crate::tree::document::Document;
9
10use std::ffi::CString;
11use std::os::raw::c_char;
12
13/// Wrapper on xmlSchemaParserCtxt
14pub struct SchemaParserContext {
15  inner: *mut bindings::_xmlSchemaParserCtxt,
16  errlog: *mut Vec<StructuredError>,
17}
18
19impl SchemaParserContext {
20  /// Create a schema parsing context from a Document object
21  pub fn from_document(doc: &Document) -> Self {
22    let parser = unsafe { bindings::xmlSchemaNewDocParserCtxt(doc.doc_ptr()) };
23
24    if parser.is_null() {
25      panic!("Failed to create schema parser context from XmlDocument"); // TODO error handling
26    }
27
28    Self::from_raw(parser)
29  }
30
31  /// Create a schema parsing context from a buffer in memory
32  pub fn from_buffer<Bytes: AsRef<[u8]>>(buff: Bytes) -> Self {
33    let buff_bytes = buff.as_ref();
34    let buff_ptr = buff_bytes.as_ptr() as *const c_char;
35    let buff_len = buff_bytes.len() as i32;
36
37    let parser = unsafe { bindings::xmlSchemaNewMemParserCtxt(buff_ptr, buff_len) };
38
39    if parser.is_null() {
40      panic!("Failed to create schema parser context from buffer"); // TODO error handling
41    }
42
43    Self::from_raw(parser)
44  }
45
46  /// Create a schema parsing context from an URL
47  pub fn from_file(path: &str) -> Self {
48    let path = CString::new(path).unwrap(); // TODO error handling for \0 containing strings
49    let path_ptr = path.as_bytes_with_nul().as_ptr() as *const c_char;
50
51    let parser = unsafe { bindings::xmlSchemaNewParserCtxt(path_ptr) };
52
53    if parser.is_null() {
54      panic!("Failed to create schema parser context from path"); // TODO error handling
55    }
56
57    Self::from_raw(parser)
58  }
59
60  /// Drains error log from errors that might have accumulated while parsing schema
61  pub fn drain_errors(&mut self) -> Vec<StructuredError> {
62    assert!(!self.errlog.is_null());
63    let errors = unsafe { &mut *self.errlog };
64    std::mem::take(errors)
65  }
66
67  /// Return a raw pointer to the underlying xmlSchemaParserCtxt structure
68  pub fn as_ptr(&self) -> *mut bindings::_xmlSchemaParserCtxt {
69    self.inner
70  }
71}
72
73/// Private Interface
74impl SchemaParserContext {
75  fn from_raw(parser: *mut bindings::_xmlSchemaParserCtxt) -> Self {
76    let errors: Box<Vec<StructuredError>> = Box::default();
77
78    unsafe {
79      let reference: *mut Vec<StructuredError> = std::mem::transmute(errors);
80      bindings::xmlSchemaSetParserStructuredErrors(
81        parser,
82        Some(common::structured_error_handler),
83        reference as *mut _,
84      );
85
86      Self {
87        inner: parser,
88        errlog: reference,
89      }
90    }
91  }
92}
93
94impl Drop for SchemaParserContext {
95  fn drop(&mut self) {
96    unsafe {
97      bindings::xmlSchemaFreeParserCtxt(self.inner);
98      if !self.errlog.is_null() {
99        let errors: Box<Vec<StructuredError>> = std::mem::transmute(self.errlog);
100        drop(errors)
101      }
102    }
103  }
104}