pub(crate) mod input;
pub mod push;
mod xml;
pub use push::PushParser;
use std::sync::Arc;
use crate::error::ParseError;
use crate::tree::Document;
use input::{
DEFAULT_MAX_ATTRIBUTES, DEFAULT_MAX_ATTRIBUTE_LENGTH, DEFAULT_MAX_DEPTH,
DEFAULT_MAX_ENTITY_EXPANSIONS, DEFAULT_MAX_NAME_LENGTH, DEFAULT_MAX_TEXT_LENGTH,
};
#[derive(Debug)]
pub struct ExternalEntityRequest<'a> {
pub name: &'a str,
pub system_id: &'a str,
pub public_id: Option<&'a str>,
}
pub type EntityResolver = Arc<dyn Fn(ExternalEntityRequest<'_>) -> Option<String> + Send + Sync>;
pub struct ParseOptions {
pub recover: bool,
pub no_blanks: bool,
pub max_depth: u32,
pub max_attributes: u32,
pub max_attribute_length: usize,
pub max_text_length: usize,
pub max_name_length: usize,
pub max_entity_expansions: u32,
pub entity_resolver: Option<EntityResolver>,
}
impl Clone for ParseOptions {
fn clone(&self) -> Self {
Self {
recover: self.recover,
no_blanks: self.no_blanks,
max_depth: self.max_depth,
max_attributes: self.max_attributes,
max_attribute_length: self.max_attribute_length,
max_text_length: self.max_text_length,
max_name_length: self.max_name_length,
max_entity_expansions: self.max_entity_expansions,
entity_resolver: self.entity_resolver.clone(),
}
}
}
impl std::fmt::Debug for ParseOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ParseOptions")
.field("recover", &self.recover)
.field("no_blanks", &self.no_blanks)
.field("max_depth", &self.max_depth)
.field("max_attributes", &self.max_attributes)
.field("max_attribute_length", &self.max_attribute_length)
.field("max_text_length", &self.max_text_length)
.field("max_name_length", &self.max_name_length)
.field("max_entity_expansions", &self.max_entity_expansions)
.field(
"entity_resolver",
&self.entity_resolver.as_ref().map(|_| "..."),
)
.finish()
}
}
impl Default for ParseOptions {
fn default() -> Self {
Self {
recover: false,
no_blanks: false,
max_depth: DEFAULT_MAX_DEPTH,
max_attributes: DEFAULT_MAX_ATTRIBUTES,
max_attribute_length: DEFAULT_MAX_ATTRIBUTE_LENGTH,
max_text_length: DEFAULT_MAX_TEXT_LENGTH,
max_name_length: DEFAULT_MAX_NAME_LENGTH,
max_entity_expansions: DEFAULT_MAX_ENTITY_EXPANSIONS,
entity_resolver: None,
}
}
}
impl ParseOptions {
#[must_use]
pub fn recover(mut self, yes: bool) -> Self {
self.recover = yes;
self
}
#[must_use]
pub fn no_blanks(mut self, yes: bool) -> Self {
self.no_blanks = yes;
self
}
#[must_use]
pub fn max_depth(mut self, max: u32) -> Self {
self.max_depth = max;
self
}
#[must_use]
pub fn max_attributes(mut self, max: u32) -> Self {
self.max_attributes = max;
self
}
#[must_use]
pub fn max_attribute_length(mut self, max: usize) -> Self {
self.max_attribute_length = max;
self
}
#[must_use]
pub fn max_text_length(mut self, max: usize) -> Self {
self.max_text_length = max;
self
}
#[must_use]
pub fn max_name_length(mut self, max: usize) -> Self {
self.max_name_length = max;
self
}
#[must_use]
pub fn max_entity_expansions(mut self, max: u32) -> Self {
self.max_entity_expansions = max;
self
}
#[must_use]
pub fn entity_resolver(
mut self,
resolver: impl Fn(ExternalEntityRequest<'_>) -> Option<String> + Send + Sync + 'static,
) -> Self {
self.entity_resolver = Some(Arc::new(resolver));
self
}
}
pub fn parse_str(input: &str) -> Result<Document, ParseError> {
parse_str_with_options(input, &ParseOptions::default())
}
pub fn parse_str_with_options(input: &str, options: &ParseOptions) -> Result<Document, ParseError> {
let mut parser = xml::XmlParser::new(input, options);
parser.parse()
}