1use {DomNode, DomNodes, DomValue, KeyValue, Listeners};
11use processors::{DomNodeProcessor, EmptyListeners};
12
13use opt_std::marker::PhantomData;
14
15pub struct TagProperties<
24 Message,
25 Children: DomNodes<Message>,
26 Attributes: AsRef<[KeyValue]>,
27 Listens: Listeners<Message>>
28{
29 children: Children,
30 key: Option<u32>,
31 attributes: Attributes,
32 listeners: Listens,
33 msg_marker: PhantomData<Message>,
34}
35
36type EmptyAttrs = [KeyValue; 0];
37
38pub fn attributes<A: AsRef<[KeyValue]>>(attrs: A) -> Attrs<A> {
58 Attrs(attrs)
59}
60
61pub struct Attrs<A: AsRef<[KeyValue]>>(A);
63
64impl<M, C: DomNodes<M>> From<C> for TagProperties<M, C, EmptyAttrs, EmptyListeners> {
66 fn from(nodes: C) -> TagProperties<M, C, EmptyAttrs, EmptyListeners> {
67 TagProperties {
68 children: nodes,
69 key: None,
70 attributes: [],
71 listeners: EmptyListeners,
72 msg_marker: PhantomData,
73 }
74 }
75}
76
77impl<M, A: AsRef<[KeyValue]>>
79 From<Attrs<A>> for TagProperties<M, (), A, EmptyListeners>
80{
81 fn from(props: Attrs<A>) -> TagProperties<M, (), A, EmptyListeners> {
82 TagProperties {
83 children: (),
84 key: None,
85 attributes: props.0,
86 listeners: EmptyListeners,
87 msg_marker: PhantomData,
88 }
89 }
90}
91
92impl<M, L: Listeners<M>>
94 From<L> for TagProperties<M, (), EmptyAttrs, L>
95{
96 fn from(props: L) -> TagProperties<M, (), EmptyAttrs, L> {
97 TagProperties {
98 children: (),
99 key: None,
100 attributes: [],
101 listeners: props,
102 msg_marker: PhantomData,
103 }
104 }
105}
106
107impl<M, C: DomNodes<M>, A: AsRef<[KeyValue]>>
109 From<(Attrs<A>, C)> for TagProperties<M, C, A, EmptyListeners>
110{
111 fn from(props: (Attrs<A>, C)) -> TagProperties<M, C, A, EmptyListeners> {
112 TagProperties {
113 children: props.1,
114 key: None,
115 attributes: (props.0).0,
116 listeners: EmptyListeners,
117 msg_marker: PhantomData,
118 }
119 }
120}
121
122impl<M, A: AsRef<[KeyValue]>, L: Listeners<M>>
124 From<(Attrs<A>, L)> for TagProperties<M, (), A, L>
125{
126 fn from(props: (Attrs<A>, L)) -> TagProperties<M, (), A, L> {
127 TagProperties {
128 children: (),
129 key: None,
130 attributes: (props.0).0,
131 listeners: props.1,
132 msg_marker: PhantomData,
133 }
134 }
135}
136
137impl<M, C: DomNodes<M>, L: Listeners<M>>
139 From<(L, C)> for TagProperties<M, C, EmptyAttrs, L>
140{
141 fn from(props: (L, C)) -> TagProperties<M, C, EmptyAttrs, L> {
142 TagProperties {
143 children: props.1,
144 key: None,
145 attributes: [],
146 listeners: props.0,
147 msg_marker: PhantomData,
148 }
149 }
150}
151
152impl<M, C: DomNodes<M>, A: AsRef<[KeyValue]>, L: Listeners<M>>
154 From<(Attrs<A>, L, C)> for TagProperties<M, C, A, L>
155{
156 fn from(props: (Attrs<A>, L, C)) -> TagProperties<M, C, A, L> {
157 TagProperties {
158 children: props.2,
159 key: None,
160 attributes: (props.0).0,
161 listeners: props.1,
162 msg_marker: PhantomData,
163 }
164 }
165}
166
167#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
169pub struct Tag<
170 Message,
171 Children: DomNodes<Message>,
172 Attributes: AsRef<[KeyValue]>,
173 L: Listeners<Message>>
174{
175 tagname: &'static str,
176 children: Children,
177 key: Option<u32>,
178 attributes: Attributes,
179 listeners: L,
180 msg_marker: PhantomData<Message>,
181}
182
183impl<
184 M,
185 C: DomNodes<M>,
186 A: AsRef<[KeyValue]>,
187 L: Listeners<M>> DomNodes<M> for Tag<M, C, A, L>
188{
189 fn process_all<'a, P: DomNodeProcessor<'a, M>>(&'a self, acc: &mut P::Acc) -> Result<(), P::Error> {
190 P::get_processor()(acc, self)
191 }
192}
193impl<M, C: DomNodes<M>, A: AsRef<[KeyValue]>, L: Listeners<M>> DomNode<M> for Tag<M, C, A, L> {
194 type Children = C;
195 type Listeners = L;
196 type WithoutListeners = Tag<M, C, A, EmptyListeners>;
197 fn key(&self) -> Option<u32> { self.key }
198 fn get_attribute(&self, index: usize) -> Option<&KeyValue> {
199 self.attributes.as_ref().get(index)
200 }
201 fn children(&self) -> &Self::Children {
202 &self.children
203 }
204 fn listeners(&self) -> &Self::Listeners {
205 &self.listeners
206 }
207 fn children_and_listeners(&self) -> (&Self::Children, &Self::Listeners) {
208 (&self.children, &self.listeners)
209 }
210 fn split_listeners(self) -> (Self::WithoutListeners, Self::Listeners) {
211 let Tag { tagname, children, key, attributes, listeners, msg_marker } = self;
212 (
213 Tag {
214 tagname: tagname,
215 children: children,
216 key: key,
217 attributes: attributes,
218 listeners: EmptyListeners,
219 msg_marker: msg_marker,
220 },
221 listeners
222 )
223 }
224 fn value(&self) -> DomValue {
225 DomValue::Element {
226 tag: self.tagname,
227 }
228 }
229}
230
231#[cfg(any(feature = "use_std", test))]
232use std::fmt;
233#[cfg(any(feature = "use_std", test))]
234impl<M, C, A, L> fmt::Display for Tag<M, C, A, L>
235 where
236 C: DomNodes<M>,
237 A: AsRef<[KeyValue]>,
238 L: Listeners<M>
239{
240 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
241 self.displayable().fmt(formatter)
242 }
243}
244
245
246macro_rules! impl_tags {
247 ($($tagname:ident),*) => { $(
248 pub fn $tagname<
255 M,
256 C: DomNodes<M>,
257 A: AsRef<[KeyValue]>,
258 L: Listeners<M>,
259 T: Into<TagProperties<M, C, A, L>>
260 >(properties: T)
261 -> Tag<M, C, A, L>
262 {
263 let TagProperties {
264 children,
265 key,
266 attributes,
267 listeners,
268 msg_marker,
269 } = properties.into();
270
271 Tag {
272 tagname: stringify!($tagname),
273 children: children,
274 key: key,
275 attributes: attributes,
276 listeners: listeners,
277 msg_marker: msg_marker,
278 }
279 }
280 )* }
281}
282
283impl_tags!(
284 a, abbr, acronym, address, applet, area, article, aside, audio, b, base, basefont, bdi,
285 bdo, big, blockquote, body, br, button, canvas, caption, center, cite, code, col, colgroup,
286 datalist, dd, del, details, dfn, dialog, dir, div, dl, dt, em, embed, fieldset,
287 figcaption, figure, font, footer, form, frame, framset, h1, h2, h3, h4, h5, h6, head,
288 header, hr, i, iframe, img, input, ins, kbd, keygen, label, legend, li, link, main, map,
289 mark, menu, menuitem, meta, meter, nav, noframes, noscript, object, ol, optgroup, option,
290 output, p, param, pre, progress, q, rp, rt, ruby, s, samp, script, section, select, small,
291 source, span, strike, strong, style, sub, summary, sup, table, tbody, td, textarea, tfoot,
292 th, thead, time, title, tr, track, tt, u, ul, var, video, wbr
293);