use std::ffi::CString;
use tinyxml2::{Document, NodeId, NodeKind, ParseErrorKind, XmlError, XmlPrinter};
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TxNodeId {
pub index: u32,
pub generation: u32,
}
pub const TX_NULL_NODE: TxNodeId = TxNodeId {
index: u32::MAX,
generation: 0,
};
impl TxNodeId {
#[inline]
pub fn from_node_id(id: NodeId) -> Self {
let (index, generation) = id.raw_parts();
Self { index, generation }
}
#[inline]
pub fn to_node_id(self) -> NodeId {
NodeId::from_raw_parts(self.index, self.generation)
}
#[inline]
pub fn is_null(self) -> bool {
self == TX_NULL_NODE
}
#[inline]
pub fn from_option(opt: Option<NodeId>) -> Self {
match opt {
Some(id) => Self::from_node_id(id),
None => TX_NULL_NODE,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TxNodeType {
TxNodeDocument = 0,
TxNodeElement = 1,
TxNodeText = 2,
TxNodeComment = 3,
TxNodeDeclaration = 4,
TxNodeUnknown = 5,
}
impl TxNodeType {
pub fn from_node_kind(kind: &NodeKind) -> Self {
match kind {
NodeKind::Document => Self::TxNodeDocument,
NodeKind::Element(_) => Self::TxNodeElement,
NodeKind::Text(_) => Self::TxNodeText,
NodeKind::Comment(_) => Self::TxNodeComment,
NodeKind::Declaration(_) => Self::TxNodeDeclaration,
NodeKind::Unknown(_) => Self::TxNodeUnknown,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TxError {
TxSuccess = 0,
TxErrorEmptyDocument = 1,
TxErrorParsingElement = 2,
TxErrorParsingAttribute = 3,
TxErrorParsingText = 4,
TxErrorParsingCdata = 5,
TxErrorParsingComment = 6,
TxErrorParsingDeclaration = 7,
TxErrorParsingUnknown = 8,
TxErrorMismatchedElement = 9,
TxErrorFileNotFound = 10,
TxErrorFileRead = 11,
TxErrorElementDepthExceeded = 12,
TxErrorNoAttribute = 13,
TxErrorWrongAttributeType = 14,
TxErrorCanNotConvertText = 15,
TxErrorNoTextNode = 16,
TxErrorInvalidNodeId = 17,
}
impl TxError {
pub fn from_xml_error(err: &XmlError) -> Self {
match err {
XmlError::EmptyDocument => Self::TxErrorEmptyDocument,
XmlError::Parse { kind, .. } => match kind {
ParseErrorKind::Element | ParseErrorKind::General => Self::TxErrorParsingElement,
ParseErrorKind::Attribute => Self::TxErrorParsingAttribute,
ParseErrorKind::Text => Self::TxErrorParsingText,
ParseErrorKind::Cdata => Self::TxErrorParsingCdata,
ParseErrorKind::Comment => Self::TxErrorParsingComment,
ParseErrorKind::Declaration => Self::TxErrorParsingDeclaration,
ParseErrorKind::Unknown => Self::TxErrorParsingUnknown,
},
XmlError::MismatchedElement { .. } => Self::TxErrorMismatchedElement,
XmlError::Io(io_err) => {
if io_err.kind() == std::io::ErrorKind::NotFound {
Self::TxErrorFileNotFound
} else {
Self::TxErrorFileRead
}
}
XmlError::ElementDepthExceeded { .. } => Self::TxErrorElementDepthExceeded,
XmlError::NoAttribute => Self::TxErrorNoAttribute,
XmlError::WrongAttributeType => Self::TxErrorWrongAttributeType,
XmlError::CanNotConvertText => Self::TxErrorCanNotConvertText,
XmlError::NoTextNode => Self::TxErrorNoTextNode,
XmlError::InvalidNodeId => Self::TxErrorInvalidNodeId,
}
}
pub fn from_result<T>(result: &tinyxml2::Result<T>) -> Self {
match result {
Ok(_) => Self::TxSuccess,
Err(e) => Self::from_xml_error(e),
}
}
}
pub struct TxDocument {
pub(crate) doc: Document,
pub(crate) cached_to_string: Option<CString>,
pub(crate) cached_to_string_compact: Option<CString>,
pub(crate) cached_error_name: Option<CString>,
pub(crate) string_cache: Vec<CString>,
}
impl TxDocument {
pub fn new() -> Self {
Self {
doc: Document::new(),
cached_to_string: None,
cached_to_string_compact: None,
cached_error_name: None,
string_cache: Vec::new(),
}
}
pub fn invalidate_caches(&mut self) {
self.cached_to_string = None;
self.cached_to_string_compact = None;
self.cached_error_name = None;
self.string_cache.clear();
}
}
impl Default for TxDocument {
fn default() -> Self {
Self::new()
}
}
pub struct TxPrinter {
pub(crate) printer: XmlPrinter,
pub(crate) cached_result: Option<CString>,
}
impl TxPrinter {
pub fn new(compact: bool) -> Self {
let printer = if compact {
XmlPrinter::new_compact()
} else {
XmlPrinter::new()
};
Self {
printer,
cached_result: None,
}
}
}