1use std::{
2 collections::HashMap,
3 ops::Deref,
4 option::{IntoIter, Iter, IterMut},
5};
6
7use yew::{html::IntoPropValue, AttrValue};
8
9#[derive(Clone, Debug, Default, PartialEq)]
10pub struct Attributes(Option<HashMap<AttrValue, Option<AttrValue>>>);
11
12impl Attributes {
13 pub fn with_defaults<I: Into<Attributes>>(mut self, defaults: I) -> Attributes {
14 let defaults: Attributes = defaults.into();
15
16 self.0 = match (self.0, defaults.0) {
17 (Some(map), Some(defaults)) => Some(defaults.into_iter().chain(map).collect()),
18 (Some(map), None) => Some(map),
19 (None, Some(defaults)) => Some(defaults),
20 (None, None) => None,
21 };
22
23 self
24 }
25}
26
27impl Deref for Attributes {
28 type Target = Option<HashMap<AttrValue, Option<AttrValue>>>;
29
30 fn deref(&self) -> &Self::Target {
31 &self.0
32 }
33}
34
35impl From<HashMap<AttrValue, Option<AttrValue>>> for Attributes {
36 fn from(value: HashMap<AttrValue, Option<AttrValue>>) -> Attributes {
37 Attributes(Some(value))
38 }
39}
40
41impl From<HashMap<AttrValue, AttrValue>> for Attributes {
42 fn from(value: HashMap<AttrValue, AttrValue>) -> Attributes {
43 Attributes(Some(
44 value
45 .into_iter()
46 .map(|(key, value)| (key, Some(value)))
47 .collect(),
48 ))
49 }
50}
51
52impl From<HashMap<String, Option<String>>> for Attributes {
53 fn from(value: HashMap<String, Option<String>>) -> Attributes {
54 Attributes(Some(
55 value
56 .into_iter()
57 .map(|(key, value)| (AttrValue::from(key), value.map(AttrValue::from)))
58 .collect(),
59 ))
60 }
61}
62
63impl From<HashMap<String, String>> for Attributes {
64 fn from(value: HashMap<String, String>) -> Attributes {
65 Attributes(Some(
66 value
67 .into_iter()
68 .map(|(key, value)| (AttrValue::from(key), Some(AttrValue::from(value))))
69 .collect(),
70 ))
71 }
72}
73
74impl<const N: usize> From<[(AttrValue, Option<AttrValue>); N]> for Attributes {
75 fn from(value: [(AttrValue, Option<AttrValue>); N]) -> Attributes {
76 Attributes(Some(HashMap::from_iter(value)))
77 }
78}
79
80impl<const N: usize> From<[(AttrValue, AttrValue); N]> for Attributes {
81 fn from(value: [(AttrValue, AttrValue); N]) -> Attributes {
82 Attributes(Some(HashMap::from_iter(
83 value.map(|(key, value)| (key, Some(value))),
84 )))
85 }
86}
87
88impl<const N: usize> From<[(&str, Option<&str>); N]> for Attributes {
89 fn from(value: [(&str, Option<&str>); N]) -> Attributes {
90 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
91 (
92 AttrValue::from(key.to_string()),
93 value.map(|value| AttrValue::from(value.to_string())),
94 )
95 }))))
96 }
97}
98
99impl<const N: usize> From<[(&str, &str); N]> for Attributes {
100 fn from(value: [(&str, &str); N]) -> Attributes {
101 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
102 (
103 AttrValue::from(key.to_string()),
104 Some(AttrValue::from(value.to_string())),
105 )
106 }))))
107 }
108}
109
110impl<const N: usize> From<[(&str, Option<String>); N]> for Attributes {
111 fn from(value: [(&str, Option<String>); N]) -> Attributes {
112 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
113 (AttrValue::from(key.to_string()), value.map(AttrValue::from))
114 }))))
115 }
116}
117
118impl<const N: usize> From<[(&str, String); N]> for Attributes {
119 fn from(value: [(&str, String); N]) -> Attributes {
120 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
121 (
122 AttrValue::from(key.to_string()),
123 Some(AttrValue::from(value)),
124 )
125 }))))
126 }
127}
128
129impl<const N: usize> From<[(String, Option<String>); N]> for Attributes {
130 fn from(value: [(String, Option<String>); N]) -> Attributes {
131 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
132 (AttrValue::from(key), value.map(AttrValue::from))
133 }))))
134 }
135}
136
137impl<const N: usize> From<[(String, String); N]> for Attributes {
138 fn from(value: [(String, String); N]) -> Attributes {
139 Attributes(Some(HashMap::from_iter(value.map(|(key, value)| {
140 (AttrValue::from(key), Some(AttrValue::from(value)))
141 }))))
142 }
143}
144
145impl<'a> IntoIterator for &'a Attributes {
146 type Item = &'a HashMap<AttrValue, Option<AttrValue>>;
147 type IntoIter = Iter<'a, HashMap<AttrValue, Option<AttrValue>>>;
148
149 fn into_iter(self) -> Self::IntoIter {
150 self.0.iter()
151 }
152}
153
154impl<'a> IntoIterator for &'a mut Attributes {
155 type Item = &'a mut HashMap<AttrValue, Option<AttrValue>>;
156 type IntoIter = IterMut<'a, HashMap<AttrValue, Option<AttrValue>>>;
157
158 fn into_iter(self) -> Self::IntoIter {
159 self.0.iter_mut()
160 }
161}
162
163impl IntoIterator for Attributes {
164 type Item = HashMap<AttrValue, Option<AttrValue>>;
165 type IntoIter = IntoIter<HashMap<AttrValue, Option<AttrValue>>>;
166
167 fn into_iter(self) -> Self::IntoIter {
168 self.0.into_iter()
169 }
170}
171
172impl IntoPropValue<Attributes> for HashMap<AttrValue, Option<AttrValue>> {
173 fn into_prop_value(self) -> Attributes {
174 self.into()
175 }
176}
177
178impl IntoPropValue<Attributes> for HashMap<AttrValue, AttrValue> {
179 fn into_prop_value(self) -> Attributes {
180 self.into()
181 }
182}
183
184impl IntoPropValue<Attributes> for HashMap<String, Option<String>> {
185 fn into_prop_value(self) -> Attributes {
186 self.into()
187 }
188}
189
190impl IntoPropValue<Attributes> for HashMap<String, String> {
191 fn into_prop_value(self) -> Attributes {
192 self.into()
193 }
194}
195
196impl<const N: usize> IntoPropValue<Attributes> for [(AttrValue, Option<AttrValue>); N] {
197 fn into_prop_value(self) -> Attributes {
198 self.into()
199 }
200}
201
202impl<const N: usize> IntoPropValue<Attributes> for [(AttrValue, AttrValue); N] {
203 fn into_prop_value(self) -> Attributes {
204 self.into()
205 }
206}
207
208impl<const N: usize> IntoPropValue<Attributes> for [(&str, Option<&str>); N] {
209 fn into_prop_value(self) -> Attributes {
210 self.into()
211 }
212}
213
214impl<const N: usize> IntoPropValue<Attributes> for [(&str, &str); N] {
215 fn into_prop_value(self) -> Attributes {
216 self.into()
217 }
218}
219
220impl<const N: usize> IntoPropValue<Attributes> for [(&str, Option<String>); N] {
221 fn into_prop_value(self) -> Attributes {
222 self.into()
223 }
224}
225
226impl<const N: usize> IntoPropValue<Attributes> for [(&str, String); N] {
227 fn into_prop_value(self) -> Attributes {
228 self.into()
229 }
230}
231
232impl<const N: usize> IntoPropValue<Attributes> for [(String, Option<String>); N] {
233 fn into_prop_value(self) -> Attributes {
234 self.into()
235 }
236}
237
238impl<const N: usize> IntoPropValue<Attributes> for [(String, String); N] {
239 fn into_prop_value(self) -> Attributes {
240 self.into()
241 }
242}