diff options
Diffstat (limited to 'src/attribute.rs')
-rw-r--r-- | src/attribute.rs | 74 |
1 files changed, 67 insertions, 7 deletions
diff --git a/src/attribute.rs b/src/attribute.rs index 8fb4778..4ae2142 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -1,30 +1,78 @@ //! Attribute. +use std::borrow::Cow; +use std::str::Utf8Error; + use quick_xml::events::attributes::{ AttrError, Attribute as QuickXMLAttribute, Attributes, }; +use quick_xml::name::QName; +use quick_xml::Error as QuickXMLError; + +use crate::escape::EscapeError; /// Represent a XML attribute. #[derive(Debug, Clone, PartialEq)] -pub struct Attribute<'a> +pub struct Attribute<'data> { - inner: QuickXMLAttribute<'a>, + inner: QuickXMLAttribute<'data>, } -impl<'a> Attribute<'a> +impl<'data> Attribute<'data> { - /// Attribute key. + /// Returns a new `Attribute`. + pub fn new(key: &'data impl AsRef<[u8]>, value: impl Into<Cow<'data, [u8]>>) -> Self + { + Self { + inner: QuickXMLAttribute { + key: QName(key.as_ref()), + value: value.into(), + }, + } + } + + /// Returns the key. + /// + /// # Errors + /// Will return `Err` if the key is invalid UTF-8. + pub fn key(&self) -> Result<&str, Error> + { + std::str::from_utf8(self.key_bytes()).map_err(Error::KeyNotUTF8) + } + + /// Returns the key as bytes. #[must_use] - pub fn key(&self) -> &[u8] + pub fn key_bytes(&self) -> &[u8] { self.inner.key.as_ref() } - /// Attribute value. + /// Returns the value. + /// + /// # Errors + /// Will return `Err` if: + /// - The value is invalid UTF-8 + /// - Unescaping the value fails + pub fn value(&self) -> Result<Cow<str>, Error> + { + self.inner.unescape_value().map_err(|err| match err { + QuickXMLError::NonDecodable(Some(utf8_error)) => { + Error::ValueNotUTF8(utf8_error) + } + QuickXMLError::EscapeError(escape_err) => { + Error::UnescapeValueFailed(EscapeError::from_quick_xml(escape_err)) + } + _ => { + unreachable!(); + } + }) + } + + /// Returns the value as bytes. They may or may not be escaped. #[must_use] - pub fn value(&self) -> &[u8] + pub fn value_bytes(&self) -> &[u8] { &self.inner.value } @@ -124,6 +172,18 @@ pub enum Error /// ``` #[error("Position {0}: duplicated attribute, previous declaration at position {1}")] Duplicated(usize, usize), + + /// Attribute key is not valid UTF-8. + #[error("Attribute key is not valid UTF-8")] + KeyNotUTF8(#[source] Utf8Error), + + /// Attribute value is not valid UTF-8. + #[error("Attribute value is not valid UTF-8")] + ValueNotUTF8(#[source] Utf8Error), + + /// Failed to unescape value. + #[error("Failed to unescape value")] + UnescapeValueFailed(#[source] EscapeError), } impl From<AttrError> for Error |