use super::*;
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct AttributeValue<'a> {
pub value: &'a str,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
impl<'a> AttributeValue<'a> {
pub fn value_raw(&self) -> &'a str {
if self.value.len() < 2 {
return self.value;
}
let bytes = self.value.as_bytes();
let first = bytes[0];
let last = bytes[bytes.len() - 1];
if (first == b'"' && last == b'"') || (first == b'\'' && last == b'\'') {
unsafe_as_str(&bytes[1..bytes.len() - 1])
}
else {
self.value
}
}
pub fn value(&self) -> Cow<'a, str> {
let unquoted = self.value_raw();
if unquoted.contains('&') {
Cow::Owned(entity::decode_entities(unquoted))
}
else {
Cow::Borrowed(unquoted)
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Attribute<'a> {
pub key: &'a str,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none", serialize_with = "serialize_attr_value"))]
pub value: Option<AttributeValue<'a>>,
#[cfg_attr(feature = "serde", serde(skip))]
pub key_span: Span,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[cfg(feature = "serde")]
fn serialize_attr_value<'a, S: serde::Serializer>(
value: &Option<AttributeValue<'a>>,
serializer: S,
) -> Result<S::Ok, S::Error> {
match value {
Some(attr_value) => serializer.serialize_some(&attr_value.value_raw()),
None => serializer.serialize_none(),
}
}