1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
//! Types for HTML attributes.
use std::collections::{btree_map, BTreeMap};
use std::iter::FromIterator;
use std::ops::{Index, Range};
use crate::offset::Offset;
/// A map of HTML attributes.
///
/// Does not preserve the order of attributes.
/// Iterating always yields attributes in order by name.
///
/// # Example
///
/// ```
/// # use html5tokenizer::attr::AttributeMap;
/// let attrs: AttributeMap<()> = vec![("href".into(), "http://example.com".into())]
/// .into_iter()
/// .collect();
/// assert_eq!(&attrs["href"], "http://example.com");
/// ```
#[derive(Debug, Default, PartialEq, Eq)]
pub struct AttributeMap<O> {
pub(crate) inner: BTreeMap<String, AttrInternal<O>>,
}
/// The value type internally used by the [`AttributeMap`].
/// Not part of the public API.
#[derive(Debug, Eq, PartialEq)]
pub(crate) struct AttrInternal<O> {
pub value: String,
pub name_span: Range<O>,
pub value_span: Range<O>,
}
/// An HTML attribute borrowed from an [`AttributeMap`].
#[derive(Debug, Eq, PartialEq)]
pub struct Attribute<'a, O> {
name: &'a str,
map_val: &'a AttrInternal<O>,
}
impl<O> AttributeMap<O> {
/// Returns the attribute with the given name.
pub fn get(&self, name: &str) -> Option<Attribute<O>> {
self.inner
.get_key_value(name)
.map(|(name, map_val)| Attribute { name, map_val })
}
}
impl<'a, O: Offset> Attribute<'a, O> {
/// Returns the attribute name.
pub fn name(&self) -> &'a str {
self.name
}
/// Returns the attribute value.
pub fn value(&self) -> &'a str {
&self.map_val.value
}
/// Returns the span of the attribute name.
pub fn name_span(&self) -> Range<O> {
self.map_val.name_span.clone()
}
/// Returns the span of the attribute value.
pub fn value_span(&self) -> Range<O> {
self.map_val.value_span.clone()
}
}
// We cannot impl Index<Output=Attribute> because Index::index returns a reference of
// the Output type (and you cannot return a value referencing a temporary value).
impl<O> Index<&str> for AttributeMap<O> {
type Output = str;
fn index(&self, name: &str) -> &Self::Output {
&self.inner[name].value
}
}
impl<'a, O> IntoIterator for &'a AttributeMap<O> {
type Item = Attribute<'a, O>;
type IntoIter = AttrIter<'a, O>;
fn into_iter(self) -> Self::IntoIter {
AttrIter(self.inner.iter())
}
}
/// A borrowed iterator over the attributes of an [`AttributeMap`].
pub struct AttrIter<'a, S>(btree_map::Iter<'a, String, AttrInternal<S>>);
impl<'a, S> Iterator for AttrIter<'a, S> {
type Item = Attribute<'a, S>;
fn next(&mut self) -> Option<Self::Item> {
let (name, map_val) = self.0.next()?;
Some(Attribute { name, map_val })
}
}
impl<O: Default> FromIterator<(String, String)> for AttributeMap<O> {
fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
Self {
inner: iter
.into_iter()
.map(|(name, value)| {
(
name,
AttrInternal {
value,
name_span: O::default()..O::default(),
value_span: O::default()..O::default(),
},
)
})
.collect(),
}
}
}
|