1use std::borrow::Cow;
4use std::str::Utf8Error;
5
6use quick_xml::events::BytesStart;
7
8use crate::attribute::{Attribute, Error as AttributeError, Iter as AttributeIter};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct TagStart<'a>
15{
16 inner: BytesStart<'a>,
17}
18
19impl<'a> TagStart<'a>
20{
21 pub fn new(name: impl Into<Cow<'a, str>>) -> Self
23 {
24 Self {
25 inner: BytesStart::new(name),
26 }
27 }
28
29 #[must_use]
31 pub fn with_attributes<Attrs>(mut self, attrs: Attrs) -> Self
32 where
33 Attrs: IntoIterator<Item = Attribute<'a>>,
34 {
35 self.inner = self
36 .inner
37 .with_attributes(attrs.into_iter().map(Attribute::into_inner));
38
39 self
40 }
41
42 pub fn name(&self) -> Result<&str, TagStartError>
47 {
48 std::str::from_utf8(self.name_bytes()).map_err(TagStartError::NameNotUTF8)
49 }
50
51 #[must_use]
53 pub fn name_bytes(&self) -> &[u8]
54 {
55 let name_length = self.inner.name().as_ref().len();
56
57 &self.inner.as_ref()[..name_length]
58 }
59
60 #[must_use]
62 pub fn attributes(&'a self) -> AttributeIter<'a>
63 {
64 AttributeIter::new(self.inner.attributes())
65 }
66
67 pub fn get_attribute(
72 &self,
73 attr_name: &str,
74 ) -> Result<Option<Attribute>, TagStartError>
75 {
76 for attr_result in self.inner.attributes().with_checks(false) {
77 let attr = attr_result.map_err(AttributeError::from)?;
78
79 if attr.key.as_ref() == attr_name.as_bytes() {
80 return Ok(Some(Attribute::from_inner(attr)));
81 }
82 }
83
84 Ok(None)
85 }
86}
87
88impl<'a> TagStart<'a>
90{
91 pub(crate) fn from_inner(inner: BytesStart<'a>) -> Self
92 {
93 Self { inner }
94 }
95}
96
97#[derive(Debug, thiserror::Error)]
99pub enum TagStartError
100{
101 #[error("Invalid attribute")]
103 InvalidAttribute(#[from] AttributeError),
104
105 #[error("Name is not valid UTF-8")]
107 NameNotUTF8(#[source] Utf8Error),
108}