yew_struct_component/
attributes.rs

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}