use std::fmt;
use crate::parse::{split_name, validate};
use crate::{Error, ErrorKind};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct AttributeListDefinition<'a> {
pub name: &'a str,
pub attributes: &'a str,
}
impl fmt::Display for AttributeListDefinition<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Self { name, attributes } = self;
write!(f, "<!AT {name} '{attributes}'>")
}
}
impl<'a> AttributeListDefinition<'a> {
pub(super) fn parse(source: &'a str) -> crate::Result<Self> {
let (name, attributes) = split_name(source);
if name.is_empty() {
return Err(Error::new(
"empty attribute list",
ErrorKind::IncompleteElement,
));
}
validate(name, ErrorKind::InvalidElementName)?;
Ok(Self {
name,
attributes: Self::unquote(attributes),
})
}
fn unquote(s: &str) -> &str {
let s = match s.as_bytes() {
[b'\'', s @ .., b'\''] | [b'\'', s @ ..] | [s @ .., b'\''] | s => s,
};
unsafe { str::from_utf8_unchecked(s) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fmt_attlist() {
let def = AttributeListDefinition {
name: "custom",
attributes: "color=red background=white flags",
};
assert_eq!(
def.to_string(),
"<!AT custom 'color=red background=white flags'>"
);
}
}