#![allow(unsafe_code, clippy::missing_safety_doc)]
use std::ffi::CStr;
use std::os::raw::c_char;
use crate::tree::Document;
use crate::validation::dtd::{self, Dtd};
use crate::validation::relaxng::{self, RelaxNgSchema};
use crate::validation::schematron::{self, SchematronSchema};
use crate::validation::xsd::{self, XsdSchema};
use crate::validation::ValidationResult;
use super::strings::to_c_string;
use super::{clear_last_error, set_last_error};
#[no_mangle]
pub unsafe extern "C" fn xmloxide_parse_dtd(input: *const c_char) -> *mut Dtd {
clear_last_error();
if input.is_null() {
set_last_error("null input pointer");
return std::ptr::null_mut();
}
let c_str = unsafe { CStr::from_ptr(input) };
let Ok(s) = c_str.to_str() else {
set_last_error("invalid UTF-8");
return std::ptr::null_mut();
};
match dtd::parse_dtd(s) {
Ok(dtd) => Box::into_raw(Box::new(dtd)),
Err(e) => {
set_last_error(&e.message);
std::ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_free_dtd(dtd: *mut Dtd) {
if !dtd.is_null() {
unsafe {
drop(Box::from_raw(dtd));
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validate_dtd(
doc: *mut Document,
dtd: *const Dtd,
) -> *mut ValidationResult {
clear_last_error();
if doc.is_null() || dtd.is_null() {
set_last_error("null pointer argument");
return std::ptr::null_mut();
}
let doc = unsafe { &mut *doc };
let dtd = unsafe { &*dtd };
let result = dtd::validate(doc, dtd);
Box::into_raw(Box::new(result))
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_parse_relaxng(input: *const c_char) -> *mut RelaxNgSchema {
clear_last_error();
if input.is_null() {
set_last_error("null input pointer");
return std::ptr::null_mut();
}
let c_str = unsafe { CStr::from_ptr(input) };
let Ok(s) = c_str.to_str() else {
set_last_error("invalid UTF-8");
return std::ptr::null_mut();
};
match relaxng::parse_relaxng(s) {
Ok(schema) => Box::into_raw(Box::new(schema)),
Err(e) => {
set_last_error(&e.message);
std::ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_free_relaxng(schema: *mut RelaxNgSchema) {
if !schema.is_null() {
unsafe {
drop(Box::from_raw(schema));
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validate_relaxng(
doc: *const Document,
schema: *const RelaxNgSchema,
) -> *mut ValidationResult {
clear_last_error();
if doc.is_null() || schema.is_null() {
set_last_error("null pointer argument");
return std::ptr::null_mut();
}
let doc = unsafe { &*doc };
let schema = unsafe { &*schema };
let result = relaxng::validate(doc, schema);
Box::into_raw(Box::new(result))
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_parse_xsd(input: *const c_char) -> *mut XsdSchema {
clear_last_error();
if input.is_null() {
set_last_error("null input pointer");
return std::ptr::null_mut();
}
let c_str = unsafe { CStr::from_ptr(input) };
let Ok(s) = c_str.to_str() else {
set_last_error("invalid UTF-8");
return std::ptr::null_mut();
};
match xsd::parse_xsd(s) {
Ok(schema) => Box::into_raw(Box::new(schema)),
Err(e) => {
set_last_error(&e.message);
std::ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_free_xsd(schema: *mut XsdSchema) {
if !schema.is_null() {
unsafe {
drop(Box::from_raw(schema));
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validate_xsd(
doc: *const Document,
schema: *const XsdSchema,
) -> *mut ValidationResult {
clear_last_error();
if doc.is_null() || schema.is_null() {
set_last_error("null pointer argument");
return std::ptr::null_mut();
}
let doc = unsafe { &*doc };
let schema = unsafe { &*schema };
let result = xsd::validate_xsd(doc, schema);
Box::into_raw(Box::new(result))
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validation_is_valid(result: *const ValidationResult) -> i32 {
if result.is_null() {
return 0;
}
let result = unsafe { &*result };
i32::from(result.is_valid)
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validation_error_count(result: *const ValidationResult) -> usize {
if result.is_null() {
return 0;
}
let result = unsafe { &*result };
result.errors.len()
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validation_error_message(
result: *const ValidationResult,
index: usize,
) -> *mut c_char {
if result.is_null() {
return std::ptr::null_mut();
}
let result = unsafe { &*result };
match result.errors.get(index) {
Some(err) => to_c_string(&err.to_string()),
None => std::ptr::null_mut(),
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validation_warning_count(
result: *const ValidationResult,
) -> usize {
if result.is_null() {
return 0;
}
let result = unsafe { &*result };
result.warnings.len()
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validation_warning_message(
result: *const ValidationResult,
index: usize,
) -> *mut c_char {
if result.is_null() {
return std::ptr::null_mut();
}
let result = unsafe { &*result };
match result.warnings.get(index) {
Some(warn) => to_c_string(&warn.to_string()),
None => std::ptr::null_mut(),
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_parse_schematron(input: *const c_char) -> *mut SchematronSchema {
clear_last_error();
if input.is_null() {
set_last_error("null input pointer");
return std::ptr::null_mut();
}
let c_str = unsafe { CStr::from_ptr(input) };
let Ok(s) = c_str.to_str() else {
set_last_error("invalid UTF-8");
return std::ptr::null_mut();
};
match schematron::parse_schematron(s) {
Ok(schema) => Box::into_raw(Box::new(schema)),
Err(e) => {
set_last_error(&e.message);
std::ptr::null_mut()
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_free_schematron(schema: *mut SchematronSchema) {
if !schema.is_null() {
unsafe {
drop(Box::from_raw(schema));
}
}
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validate_schematron(
doc: *const Document,
schema: *const SchematronSchema,
) -> *mut ValidationResult {
clear_last_error();
if doc.is_null() || schema.is_null() {
set_last_error("null pointer argument");
return std::ptr::null_mut();
}
let doc = unsafe { &*doc };
let schema = unsafe { &*schema };
let result = schematron::validate_schematron(doc, schema);
Box::into_raw(Box::new(result))
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_validate_schematron_with_phase(
doc: *const Document,
schema: *const SchematronSchema,
phase: *const c_char,
) -> *mut ValidationResult {
clear_last_error();
if doc.is_null() || schema.is_null() {
set_last_error("null pointer argument");
return std::ptr::null_mut();
}
let doc = unsafe { &*doc };
let schema = unsafe { &*schema };
if phase.is_null() {
let result = schematron::validate_schematron(doc, schema);
return Box::into_raw(Box::new(result));
}
let phase_raw = unsafe { CStr::from_ptr(phase) };
let Ok(phase_name) = phase_raw.to_str() else {
set_last_error("invalid UTF-8 in phase name");
return std::ptr::null_mut();
};
let result = schematron::validate_schematron_with_phase(doc, schema, phase_name);
Box::into_raw(Box::new(result))
}
#[no_mangle]
pub unsafe extern "C" fn xmloxide_free_validation_result(result: *mut ValidationResult) {
if !result.is_null() {
unsafe {
drop(Box::from_raw(result));
}
}
}