use std::fmt::{self, Debug};
use crate::defs::XmlLocation;
use crate::document::Document;
use crate::node::Node;
use crate::node_type::NodeType;
#[cfg(feature = "use_cstr")]
use std::ffi::CStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AttributeInfo {
name: XmlLocation,
value: XmlLocation,
}
impl AttributeInfo {
pub(crate) fn new(name: XmlLocation, value: XmlLocation) -> Self {
AttributeInfo { name, value }
}
}
pub struct Attribute<'a> {
doc: &'a Document,
data: &'a AttributeInfo,
}
impl<'xml> Attribute<'xml> {
#[inline]
#[must_use]
pub fn name(&self) -> &str {
#[cfg(feature = "use_cstr")]
{
self.doc.get_str_from_location(self.data.name)
}
#[cfg(not(feature = "use_cstr"))]
self.doc.get_str_from_location(self.data.name.clone())
}
#[inline]
#[must_use]
pub fn name_bytes(&self) -> &[u8] {
#[cfg(feature = "use_cstr")]
{
self.doc.get_cstr_from_location(self.data.name).to_bytes()
}
#[cfg(not(feature = "use_cstr"))]
&self.doc.xml[self.data.name.start as usize..self.data.name.end as usize]
}
#[cfg(feature = "use_cstr")]
#[inline]
#[must_use]
pub fn name_cstr(&self) -> &CStr {
self.doc.get_cstr_from_location(self.data.name)
}
#[inline]
#[must_use]
pub fn is(&self, name: &str) -> bool {
self.name() == name
}
#[inline]
#[must_use]
pub fn is_bytes(&self, name: &[u8]) -> bool {
self.name_bytes() == name
}
#[cfg(feature = "use_cstr")]
#[inline]
#[must_use]
pub fn is_cstr(&self, name: &CStr) -> bool {
self.name_cstr() == name
}
#[inline]
#[must_use]
pub fn value(&self) -> &'xml str {
#[cfg(feature = "use_cstr")]
{
self.doc.get_str_from_location(self.data.value)
}
#[cfg(not(feature = "use_cstr"))]
self.doc.get_str_from_location(self.data.value.clone())
}
#[inline]
#[must_use]
pub fn value_bytes(&self) -> &[u8] {
#[cfg(feature = "use_cstr")]
{
self.doc.get_cstr_from_location(self.data.value).to_bytes()
}
#[cfg(not(feature = "use_cstr"))]
&self.doc.xml[self.data.name.start as usize..self.data.name.end as usize]
}
#[cfg(feature = "use_cstr")]
#[inline]
#[must_use]
pub fn value_cstr(&self) -> &'xml CStr {
self.doc.get_cstr_from_location(self.data.value)
}
}
impl fmt::Debug for Attribute<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"Attribute {{ name: \"{}\", value: \"{}\" }}",
self.name(),
self.value()
)
}
}
#[derive(Clone)]
pub struct Attributes<'a> {
doc: &'a Document,
attrs: core::slice::Iter<'a, AttributeInfo>,
}
impl<'a> Attributes<'a> {
#[inline]
#[must_use]
pub fn new(node: &Node<'a>) -> Attributes<'a> {
let attrs = match node.node_info.node_type() {
NodeType::Element { ref attributes, .. } => {
&node.doc.attributes[attributes.start as usize..attributes.end as usize]
}
_ => &[],
};
Attributes {
doc: node.doc,
attrs: attrs.iter(),
}
}
}
impl<'a> Iterator for Attributes<'a> {
type Item = Attribute<'a>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.attrs.next().map(|attr| Attribute {
doc: self.doc,
data: attr,
})
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.attrs.nth(n).map(|attr| Attribute {
doc: self.doc,
data: attr,
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.attrs.size_hint()
}
}
impl DoubleEndedIterator for Attributes<'_> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.attrs.next_back().map(|attr| Attribute {
doc: self.doc,
data: attr,
})
}
}
impl ExactSizeIterator for Attributes<'_> {
}