use std::{fmt::Write as _, fs::File, sync::Arc};
use crate::{
error::XMLError,
sax::{
AttributeType, ContentSpec, DefaultDecl, Locator, attributes::Attributes,
error::SAXParseError, source::InputSource,
},
uri::URIStr,
};
pub trait SAXHandler: EntityResolver + ErrorHandler {
fn characters(&mut self, data: &str) {
let _ = data;
}
fn declaration(&mut self, version: &str, encoding: Option<&str>, standalone: Option<bool>) {
let _ = (version, encoding, standalone);
}
fn ignorable_whitespace(&mut self, data: &str) {
let _ = data;
}
fn processing_instruction(&mut self, target: &str, data: Option<&str>) {
let _ = (target, data);
}
fn set_document_locator(&mut self, locator: Arc<Locator>) {
let _ = locator;
}
fn skipped_entity(&mut self, name: &str) {
let _ = name;
}
fn start_document(&mut self) {}
fn end_document(&mut self) {}
fn start_element(
&mut self,
namespace_name: Option<&str>,
local_name: Option<&str>,
qname: &str,
atts: &Attributes,
) {
let _ = (namespace_name, local_name, qname, atts);
}
fn end_element(&mut self, namespace_name: Option<&str>, local_name: Option<&str>, qname: &str) {
let _ = (namespace_name, local_name, qname);
}
fn start_prefix_mapping(&mut self, prefix: Option<&str>, uri: &str) {
let _ = (prefix, uri);
}
fn end_prefix_mapping(&mut self, prefix: Option<&str>) {
let _ = prefix;
}
fn attribute_decl(
&mut self,
element_name: &str,
attribute_name: &str,
attribute_type: &AttributeType,
default_decl: &DefaultDecl,
) {
let _ = (element_name, attribute_name, attribute_type, default_decl);
}
fn element_decl(&mut self, name: &str, contentspec: &ContentSpec) {
let _ = (name, contentspec);
}
fn external_entity_decl(&mut self, name: &str, public_id: Option<&str>, system_id: &URIStr) {
let _ = (name, public_id, system_id);
}
fn internal_entity_decl(&mut self, name: &str, value: &str) {
let _ = (name, value);
}
fn notation_decl(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
let _ = (name, public_id, system_id);
}
fn unparsed_entity_decl(
&mut self,
name: &str,
public_id: Option<&str>,
system_id: &URIStr,
notation_name: &str,
) {
let _ = (name, public_id, system_id, notation_name);
}
fn comment(&mut self, data: &str) {
let _ = data;
}
fn start_cdata(&mut self) {}
fn end_cdata(&mut self) {}
fn start_dtd(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
let _ = (name, public_id, system_id);
}
fn end_dtd(&mut self) {}
fn start_entity(&mut self, name: &str) {
let _ = name;
}
fn end_entity(&mut self) {}
}
pub trait EntityResolver {
fn get_external_subset(
&mut self,
name: &str,
base_uri: Option<&URIStr>,
) -> Result<InputSource<'static>, XMLError> {
let _ = (name, base_uri);
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("An external subset '{}' is not found.", name),
)
.into())
}
fn resolve_entity(
&mut self,
name: &str,
public_id: Option<&str>,
base_uri: &URIStr,
system_id: &URIStr,
) -> Result<InputSource<'static>, XMLError> {
let (_, _) = (name, public_id);
let path = base_uri.resolve(system_id);
let file = File::open(path.path())?;
let mut reader = InputSource::from_reader(file, None)?;
reader.set_system_id(path);
Ok(reader)
}
}
pub trait ErrorHandler {
fn error(&mut self, error: SAXParseError) {
let _ = error;
}
fn fatal_error(&mut self, error: SAXParseError) {
let _ = error;
}
fn warning(&mut self, error: SAXParseError) {
let _ = error;
}
}
impl<H: EntityResolver> EntityResolver for &mut H {
fn resolve_entity(
&mut self,
name: &str,
public_id: Option<&str>,
base_uri: &URIStr,
system_id: &URIStr,
) -> Result<InputSource<'static>, XMLError> {
(*self).resolve_entity(name, public_id, base_uri, system_id)
}
fn get_external_subset(
&mut self,
name: &str,
base_uri: Option<&URIStr>,
) -> Result<InputSource<'static>, XMLError> {
(*self).get_external_subset(name, base_uri)
}
}
impl<H: ErrorHandler> ErrorHandler for &mut H {
fn error(&mut self, error: SAXParseError) {
(*self).error(error);
}
fn fatal_error(&mut self, error: SAXParseError) {
(*self).fatal_error(error);
}
fn warning(&mut self, error: SAXParseError) {
(*self).warning(error);
}
}
impl<H: SAXHandler> SAXHandler for &mut H {
fn attribute_decl(
&mut self,
element_name: &str,
attribute_name: &str,
attribute_type: &AttributeType,
default_decl: &DefaultDecl,
) {
(*self).attribute_decl(element_name, attribute_name, attribute_type, default_decl);
}
fn characters(&mut self, data: &str) {
(*self).characters(data);
}
fn comment(&mut self, data: &str) {
(*self).comment(data);
}
fn declaration(&mut self, version: &str, encoding: Option<&str>, standalone: Option<bool>) {
(*self).declaration(version, encoding, standalone);
}
fn element_decl(&mut self, name: &str, contentspec: &ContentSpec) {
(*self).element_decl(name, contentspec);
}
fn end_cdata(&mut self) {
(*self).end_cdata();
}
fn end_document(&mut self) {
(*self).end_document();
}
fn end_dtd(&mut self) {
(*self).end_dtd();
}
fn end_element(&mut self, namespace_name: Option<&str>, local_name: Option<&str>, qname: &str) {
(*self).end_element(namespace_name, local_name, qname);
}
fn end_entity(&mut self) {
(*self).end_entity();
}
fn end_prefix_mapping(&mut self, prefix: Option<&str>) {
(*self).end_prefix_mapping(prefix);
}
fn external_entity_decl(&mut self, name: &str, public_id: Option<&str>, system_id: &URIStr) {
(*self).external_entity_decl(name, public_id, system_id);
}
fn ignorable_whitespace(&mut self, data: &str) {
(*self).ignorable_whitespace(data);
}
fn internal_entity_decl(&mut self, name: &str, value: &str) {
(*self).internal_entity_decl(name, value);
}
fn notation_decl(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
(*self).notation_decl(name, public_id, system_id);
}
fn processing_instruction(&mut self, target: &str, data: Option<&str>) {
(*self).processing_instruction(target, data);
}
fn set_document_locator(&mut self, locator: Arc<Locator>) {
(*self).set_document_locator(locator);
}
fn skipped_entity(&mut self, name: &str) {
(*self).skipped_entity(name);
}
fn start_cdata(&mut self) {
(*self).start_cdata();
}
fn start_document(&mut self) {
(*self).start_document();
}
fn start_dtd(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
(*self).start_dtd(name, public_id, system_id);
}
fn start_element(
&mut self,
namespace_name: Option<&str>,
local_name: Option<&str>,
qname: &str,
atts: &Attributes,
) {
(*self).start_element(namespace_name, local_name, qname, atts);
}
fn start_entity(&mut self, name: &str) {
(*self).start_entity(name);
}
fn start_prefix_mapping(&mut self, prefix: Option<&str>, uri: &str) {
(*self).start_prefix_mapping(prefix, uri);
}
fn unparsed_entity_decl(
&mut self,
name: &str,
public_id: Option<&str>,
system_id: &URIStr,
notation_name: &str,
) {
(*self).unparsed_entity_decl(name, public_id, system_id, notation_name);
}
}
#[derive(Default)]
pub struct DefaultSAXHandler;
impl ErrorHandler for DefaultSAXHandler {
fn error(&mut self, error: SAXParseError) {
eprintln!("{error}")
}
fn fatal_error(&mut self, error: SAXParseError) {
eprintln!("{error}")
}
fn warning(&mut self, error: SAXParseError) {
eprintln!("{error}")
}
}
impl EntityResolver for DefaultSAXHandler {}
impl SAXHandler for DefaultSAXHandler {}
pub struct DebugHandler<Child: SAXHandler = DefaultSAXHandler> {
pub buffer: String,
pub child: Child,
}
impl<Child: SAXHandler> EntityResolver for DebugHandler<Child> {
fn get_external_subset(
&mut self,
name: &str,
base_uri: Option<&URIStr>,
) -> Result<InputSource<'static>, XMLError> {
writeln!(self.buffer, "getExternalSubset({name})").ok();
self.child.get_external_subset(name, base_uri)
}
fn resolve_entity(
&mut self,
name: &str,
public_id: Option<&str>,
base_uri: &URIStr,
system_id: &URIStr,
) -> Result<InputSource<'static>, XMLError> {
if name != "[document]" {
writeln!(self.buffer, "resolveEntity({name})").ok();
}
self.child
.resolve_entity(name, public_id, base_uri, system_id)
}
}
impl<Child: SAXHandler> ErrorHandler for DebugHandler<Child> {
fn error(&mut self, error: SAXParseError) {
self.child.error(error);
}
fn fatal_error(&mut self, error: SAXParseError) {
self.child.fatal_error(error);
}
fn warning(&mut self, error: SAXParseError) {
self.child.warning(error);
}
}
impl<Child: SAXHandler> SAXHandler for DebugHandler<Child> {
fn characters(&mut self, data: &str) {
writeln!(self.buffer, "characters({data})").ok();
self.child.characters(data);
}
fn declaration(&mut self, version: &str, encoding: Option<&str>, standalone: Option<bool>) {
write!(
self.buffer,
"declaration({version}, {}, ",
encoding.unwrap_or("None")
)
.ok();
if let Some(standalone) = standalone {
if standalone {
writeln!(self.buffer, "yes)").ok();
} else {
writeln!(self.buffer, "no)").ok();
}
} else {
writeln!(self.buffer, "None)").ok();
}
self.child.declaration(version, encoding, standalone);
}
fn ignorable_whitespace(&mut self, data: &str) {
writeln!(self.buffer, "ignorableWhitespace({data})").ok();
self.child.ignorable_whitespace(data);
}
fn processing_instruction(&mut self, target: &str, data: Option<&str>) {
write!(self.buffer, "processingInstruction({target}, ").ok();
if let Some(data) = data {
writeln!(self.buffer, "'{data}')").ok();
} else {
writeln!(self.buffer, "None)").ok();
}
self.child.processing_instruction(target, data);
}
fn set_document_locator(&mut self, locator: Arc<Locator>) {
writeln!(self.buffer, "setDocumentLocator()").ok();
self.child.set_document_locator(locator);
}
fn skipped_entity(&mut self, name: &str) {
writeln!(self.buffer, "skippedEntity({name})").ok();
self.child.skipped_entity(name);
}
fn start_document(&mut self) {
writeln!(self.buffer, "startDocument()").ok();
self.child.start_document();
}
fn end_document(&mut self) {
writeln!(self.buffer, "endDocument()").ok();
self.child.end_document();
}
fn start_element(
&mut self,
namespace_name: Option<&str>,
local_name: Option<&str>,
qname: &str,
atts: &Attributes,
) {
write!(
self.buffer,
"startElement({}, {}, {qname}",
namespace_name.unwrap_or("None"),
local_name.unwrap_or("None")
)
.ok();
for att in atts {
write!(self.buffer, ", ").ok();
if let Some(local_name) = att.local_name.as_deref() {
if let Some(uri) = att.namespace_name.as_deref() {
write!(self.buffer, "{{{uri}}}").ok();
}
write!(self.buffer, "{local_name}='{}'", att.value).ok();
} else {
write!(self.buffer, "{}='{}'", att.qname, att.value).ok();
}
}
writeln!(self.buffer, ")").ok();
self.child
.start_element(namespace_name, local_name, qname, atts);
}
fn end_element(&mut self, namespace_name: Option<&str>, local_name: Option<&str>, qname: &str) {
writeln!(
self.buffer,
"endElement({}, {}, {qname})",
namespace_name.unwrap_or("None"),
local_name.unwrap_or("None")
)
.ok();
self.child.end_element(namespace_name, local_name, qname);
}
fn start_prefix_mapping(&mut self, prefix: Option<&str>, uri: &str) {
writeln!(
self.buffer,
"startPrefixMapping({}, {uri})",
prefix.unwrap_or("None")
)
.ok();
self.child.start_prefix_mapping(prefix, uri);
}
fn end_prefix_mapping(&mut self, prefix: Option<&str>) {
writeln!(
self.buffer,
"endPrefixMapping({})",
prefix.unwrap_or("None")
)
.ok();
self.child.end_prefix_mapping(prefix);
}
fn attribute_decl(
&mut self,
element_name: &str,
attribute_name: &str,
attribute_type: &AttributeType,
default_decl: &DefaultDecl,
) {
writeln!(
self.buffer,
"attributeDecl({element_name}, {attribute_name}, {attribute_type}, {default_decl})"
)
.ok();
self.child
.attribute_decl(element_name, attribute_name, attribute_type, default_decl);
}
fn element_decl(&mut self, name: &str, contentspec: &ContentSpec) {
writeln!(self.buffer, "elementDecl({name}, {contentspec})").ok();
self.child.element_decl(name, contentspec);
}
fn external_entity_decl(&mut self, name: &str, public_id: Option<&str>, system_id: &URIStr) {
writeln!(
self.buffer,
"externalEntityDecl({name}, {}, {})",
public_id.unwrap_or("None"),
system_id.as_escaped_str()
)
.ok();
self.child.external_entity_decl(name, public_id, system_id);
}
fn internal_entity_decl(&mut self, name: &str, value: &str) {
writeln!(self.buffer, "internalEntityDecl({name}, {value})").ok();
self.child.internal_entity_decl(name, value);
}
fn notation_decl(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
writeln!(
self.buffer,
"notationDecl({name}, {}, {})",
public_id.unwrap_or("None"),
system_id.map_or("None", |id| id.as_escaped_str())
)
.ok();
self.child.notation_decl(name, public_id, system_id);
}
fn unparsed_entity_decl(
&mut self,
name: &str,
public_id: Option<&str>,
system_id: &URIStr,
notation_name: &str,
) {
writeln!(
self.buffer,
"unparsedEntityDecl({name}, {public_id:?}, {}, {notation_name})",
system_id.as_escaped_str()
)
.ok();
self.child
.unparsed_entity_decl(name, public_id, system_id, notation_name);
}
fn comment(&mut self, data: &str) {
writeln!(self.buffer, "comment({data})").ok();
self.child.comment(data);
}
fn start_cdata(&mut self) {
writeln!(self.buffer, "startCDATA()").ok();
self.child.start_cdata();
}
fn end_cdata(&mut self) {
writeln!(self.buffer, "endCDATA()").ok();
self.child.end_cdata();
}
fn start_dtd(&mut self, name: &str, public_id: Option<&str>, system_id: Option<&URIStr>) {
writeln!(
self.buffer,
"startDTD({name}, {}, {})",
public_id.unwrap_or("None"),
system_id.map_or("None", |id| id.as_escaped_str())
)
.ok();
self.child.start_dtd(name, public_id, system_id);
}
fn end_dtd(&mut self) {
writeln!(self.buffer, "endDTD()").ok();
self.child.end_dtd();
}
fn start_entity(&mut self, name: &str) {
writeln!(self.buffer, "startEntity({name})").ok();
self.child.start_entity(name);
}
fn end_entity(&mut self) {
writeln!(self.buffer, "endEntity()").ok();
self.child.end_entity();
}
}
impl Default for DebugHandler {
fn default() -> Self {
Self {
buffer: String::new(),
child: DefaultSAXHandler,
}
}
}