xsd_parser/xml/
attributes.rs1use std::borrow::{Borrow, Cow};
2use std::fmt::{Debug, Formatter, Result as FmtResult};
3use std::ops::{Deref, DerefMut};
4
5use encoding_rs::{Encoding, UTF_8};
6use indexmap::map::Entry;
7use quick_xml::{
8 encoding::decode,
9 escape::{resolve_predefined_entity, unescape_with},
10 events::attributes::Attribute,
11};
12
13use indexmap::IndexMap;
14use quick_xml::name::QName;
15
16use crate::models::{format_utf8_slice, RawByteStr};
17use crate::quick_xml::{Error, ErrorKind};
18
19#[derive(Default, Debug, Clone, Eq, PartialEq)]
21pub struct Attributes<'a>(pub IndexMap<Key<'a>, Value<'a>>);
22
23pub type AnyAttributes = Attributes<'static>;
25
26impl<'a> Attributes<'a> {
27 pub fn push(&mut self, attrib: Attribute<'_>) -> Result<(), Error> {
37 let key = Key(Cow::Owned(attrib.key.0.to_owned()));
38
39 match self.0.entry(key) {
40 Entry::Vacant(e) => {
41 e.insert(Value(Cow::Owned(attrib.value.into_owned())));
42
43 Ok(())
44 }
45 Entry::Occupied(e) => {
46 Err(ErrorKind::DuplicateAttribute(RawByteStr::from_slice(e.key())).into())
47 }
48 }
49 }
50
51 pub fn insert<K, V>(&mut self, key: K, value: V) -> Option<Value<'a>>
55 where
56 K: Into<Cow<'a, [u8]>>,
57 V: Into<Cow<'a, [u8]>>,
58 {
59 let key = Key(key.into());
60 let value = Value(value.into());
61
62 self.0.insert(key, value)
63 }
64
65 pub fn attributes(&self) -> impl Iterator<Item = Attribute<'_>> {
67 self.iter().map(|(k, v)| Attribute {
68 key: QName(k.as_ref()),
69 value: Cow::Borrowed(v.as_ref()),
70 })
71 }
72}
73
74impl<'a> Deref for Attributes<'a> {
75 type Target = IndexMap<Key<'a>, Value<'a>>;
76
77 fn deref(&self) -> &Self::Target {
78 &self.0
79 }
80}
81
82impl DerefMut for Attributes<'_> {
83 fn deref_mut(&mut self) -> &mut Self::Target {
84 &mut self.0
85 }
86}
87
88impl<'a> Extend<Attribute<'a>> for Attributes<'a> {
89 fn extend<T: IntoIterator<Item = Attribute<'a>>>(&mut self, iter: T) {
90 self.0.extend(iter.into_iter().map(|a| {
91 let key = Key(Cow::Borrowed(a.key.0));
92 let value = Value(a.value.clone());
93
94 (key, value)
95 }));
96 }
97}
98
99impl<'a> Extend<(Key<'a>, Value<'a>)> for Attributes<'a> {
100 fn extend<T: IntoIterator<Item = (Key<'a>, Value<'a>)>>(&mut self, iter: T) {
101 self.0.extend(iter);
102 }
103}
104
105impl<'a> FromIterator<(Key<'a>, Value<'a>)> for Attributes<'a> {
106 fn from_iter<T: IntoIterator<Item = (Key<'a>, Value<'a>)>>(iter: T) -> Self {
107 Self(FromIterator::from_iter(iter))
108 }
109}
110
111#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
113pub struct Key<'a>(pub Cow<'a, [u8]>);
114
115impl Key<'_> {
116 #[must_use]
118 pub fn qname(&self) -> QName<'_> {
119 QName(&self.0)
120 }
121}
122
123impl Deref for Key<'_> {
124 type Target = [u8];
125
126 fn deref(&self) -> &Self::Target {
127 &self.0
128 }
129}
130
131impl Debug for Key<'_> {
132 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
133 write!(f, "Key(\"")?;
134 format_utf8_slice(&self.0, f)?;
135 write!(f, "\")")?;
136
137 Ok(())
138 }
139}
140
141impl AsRef<[u8]> for Key<'_> {
142 fn as_ref(&self) -> &[u8] {
143 &self.0
144 }
145}
146
147impl Borrow<[u8]> for Key<'_> {
148 fn borrow(&self) -> &[u8] {
149 &self.0
150 }
151}
152
153#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
155pub struct Value<'a>(pub Cow<'a, [u8]>);
156
157impl Value<'_> {
158 #[inline]
164 pub fn unescape(&self) -> Result<Cow<'_, str>, Error> {
165 self.unescape_with(resolve_predefined_entity)
166 }
167
168 #[inline]
177 pub fn unescape_with<'entity>(
178 &self,
179 resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
180 ) -> Result<Cow<'_, str>, Error> {
181 self.decode_and_unescape_with(UTF_8, resolve_entity)
182 }
183
184 #[inline]
190 pub fn decode_and_unescape(&self, encoding: &'static Encoding) -> Result<Cow<'_, str>, Error> {
191 self.decode_and_unescape_with(encoding, resolve_predefined_entity)
192 }
193
194 #[inline]
203 pub fn decode_and_unescape_with<'entity>(
204 &self,
205 encoding: &'static Encoding,
206 resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
207 ) -> Result<Cow<'_, str>, Error> {
208 let decoded = decode(&self.0, encoding)?;
209
210 match unescape_with(&decoded, resolve_entity)? {
211 Cow::Borrowed(_) => Ok(decoded),
212 Cow::Owned(s) => Ok(s.into()),
213 }
214 }
215}
216
217impl Debug for Value<'_> {
218 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
219 write!(f, "Value(\"")?;
220 format_utf8_slice(&self.0, f)?;
221 write!(f, "\")")?;
222
223 Ok(())
224 }
225}
226
227impl AsRef<[u8]> for Value<'_> {
228 fn as_ref(&self) -> &[u8] {
229 &self.0
230 }
231}
232
233impl Borrow<[u8]> for Value<'_> {
234 fn borrow(&self) -> &[u8] {
235 &self.0
236 }
237}