1use wasm_bindgen::JsValue;
2
3use crate::{AnyNode, AnyNodeValue, Children, IntoElement, Keyed};
4
5pub trait Node {
11 fn to_node(&self) -> AnyNode;
12
13 #[inline]
14 fn to_children(&self) -> Option<Children> {
15 Some(Children::from_single(self.to_node()))
16 }
17
18 #[inline]
19 fn into_node(self) -> AnyNode
20 where
21 Self: Sized,
22 {
23 self.to_node()
24 }
25
26 #[inline]
27 fn into_children(self) -> Option<Children>
28 where
29 Self: Sized,
30 {
31 self.to_children()
32 }
33}
34
35impl Node for () {
36 #[inline]
37 fn to_node(&self) -> AnyNode {
38 AnyNode::Null
39 }
40
41 #[inline]
42 fn to_children(&self) -> Option<Children> {
43 None
44 }
45}
46
47impl<T: Node> Node for Option<T> {
48 #[inline]
49 fn to_node(&self) -> AnyNode {
50 if let Some(node) = self {
51 node.to_node()
52 } else {
53 AnyNode::Null
54 }
55 }
56
57 #[inline]
58 fn to_children(&self) -> Option<Children> {
59 self.as_ref().and_then(Node::to_children)
60 }
61
62 #[inline]
63 fn into_node(self) -> AnyNode {
64 self.map(Node::into_node).unwrap_or(AnyNode::Null)
65 }
66
67 #[inline]
68 fn into_children(self) -> Option<Children> {
69 self.and_then(Node::into_children)
70 }
71}
72
73macro_rules! into_js_node {
74 (into_f64: $($n:ty)*) => ($(
75 impl Node for $n {
76 #[inline]
77 fn to_node(&self) -> AnyNode {
78 (*self).into_node()
79 }
80 #[inline]
81 fn into_node(self) -> AnyNode {
82 AnyNode::Value(AnyNodeValue::unsafe_from_js_react_node(JsValue::from_f64(self.into())))
83 }
84 }
85 )*);
86 (deref: $($n:ty)*) => ($(
87 impl Node for $n {
88 #[inline]
89 fn to_node(&self) -> AnyNode {
90 AnyNode::Value(AnyNodeValue::unsafe_from_js_react_node(JsValue::from(*self)))
91 }
92 }
93 )*);
94 (bigint_to_string: $($n:ty)*) => ($(
95 impl Node for $n {
96 #[inline]
97 fn to_node(&self) -> AnyNode {
98 (*self).into_node()
99 }
100 #[inline]
101 fn into_node(self) -> AnyNode {
102 let js_bigint = js_sys::BigInt::from(self);
103 let js_string = js_bigint.to_string(10).unwrap();
104 AnyNode::Value(AnyNodeValue::unsafe_from_js_react_node(JsValue::from(js_string)))
105 }
106 }
107 )*);
108 ($($n:ty)*) => ($(
109 impl Node for $n {
110 #[inline]
111 fn to_node(&self) -> AnyNode {
112 AnyNode::Value(AnyNodeValue::unsafe_from_js_react_node(JsValue::from(self)))
113 }
114 }
115 )*);
116}
117
118into_js_node! {
119 str
120 react_sys::Element
121 String
122 js_sys::JsString
123 js_sys::Number
124 js_sys::BigInt
125 js_sys::Boolean
126}
127
128into_js_node! {
129 into_f64:
130 i8 u8 i16 u16 i32 u32 f32 f64
132}
133
134into_js_node! {
135 bigint_to_string:
136 i64 u64 i128 u128 isize usize
138}
139
140into_js_node! {
141 deref:
142 bool
143}
144
145#[inline]
146fn into_keyed_element<E: IntoElement>(el: Keyed<E>) -> Keyed<crate::Element> {
147 Keyed(el.0.into_element())
148}
149
150#[inline]
151fn option_into_keyed_element<E: IntoElement>(
152 el: Option<Keyed<E>>,
153) -> Option<Keyed<crate::Element>> {
154 el.map(into_keyed_element)
155}
156
157macro_rules! impl_node_for_iter {
158 (impl into_children) => {
159 #[inline]
160 fn into_children(self) -> Option<Children> {
161 Some(Children::from_single(self.into_node()))
162 }
163 };
164 (impl sized) => {
165 #[inline]
166 fn into_node(self) -> AnyNode {
167 AnyNode::Multiple(std::rc::Rc::new(self.into_iter().map(into_keyed_element).collect()))
168 }
169
170 impl_node_for_iter! { impl into_children }
171 };
172 (impl sized opt) => {
173 #[inline]
174 fn into_node(self) -> AnyNode {
175 AnyNode::Multiple(std::rc::Rc::new(
176 self.into_iter()
177 .filter_map(option_into_keyed_element)
178 .collect()
179 ))
180 }
181
182 impl_node_for_iter! { impl into_children }
183
184 };
185 ( $($sized:ident)? {$($t:tt)+} {$($t_opt:tt)+}) => {
186 $($t)+ {
187 #[inline]
188 fn to_node(&self) -> AnyNode {
189 self.to_vec().into_node()
190 }
191
192 $( impl_node_for_iter! { impl $sized } )?
193 }
194 $($t_opt)+ {
195 #[inline]
196 fn to_node(&self) -> AnyNode {
197 self.iter().filter_map(Clone::clone).collect::<Vec<_>>().into_node()
198 }
199
200 $( impl_node_for_iter! { impl $sized opt } )?
201 }
202 };
203}
204
205impl_node_for_iter! {
206 sized
207 { impl<E: IntoElement + Clone> Node for Vec<Keyed<E>> }
208 { impl<E: IntoElement + Clone> Node for Vec<Option<Keyed<E>>> }
209}
210impl_node_for_iter! {
211 { impl<E: IntoElement + Clone> Node for [Keyed<E>] }
212 { impl<E: IntoElement + Clone> Node for [Option<Keyed<E>>] }
213}
214impl_node_for_iter! {
215 sized
216 { impl<E: IntoElement + Clone, const S: usize> Node for [Keyed<E>; S] }
217 { impl<E: IntoElement + Clone, const S: usize> Node for [Option<Keyed<E>>; S] }
218}
219
220macro_rules! impl_node_for_tuple {
221 (@impl ( $($t:ident),+ $(,)? )) => {
222 impl<$($t: Node),+> Node for ($($t),+ ,) {
223 #[inline]
224 fn to_node(&self) -> AnyNode {
225 #![allow(non_snake_case)]
226 let ($($t),+ ,) = self;
227 let v = Children::from_static_nodes([
228 $($t.to_node()),+
229 ]);
230 v.to_node()
231 }
232 #[inline]
233 fn to_children(&self) -> Option<Children> {
234 #![allow(non_snake_case)]
235 let ($($t),+ ,) = self;
236 let v = Children::from_static_nodes([
237 $($t.to_node()),+
238 ]);
239 Some(v)
240 }
241 #[inline]
242 fn into_node(self) -> AnyNode {
243 #![allow(non_snake_case)]
244 let ($($t),+ ,) = self;
245 let v = Children::from_static_nodes([
246 $($t.into_node()),+
247 ]);
248 v.into_node()
249 }
250 #[inline]
251 fn into_children(self) -> Option<Children> {
252 #![allow(non_snake_case)]
253 let ($($t),+ ,) = self;
254 Some(Children::from_static_nodes([
255 $($t.into_node()),+
256 ]))
257 }
258 }
259 };
260 ( $(( $($t:ident),+ $(,)? ))* ) => {
261 $(
262 impl_node_for_tuple! { @impl ($($t),+ ,) }
263 )*
264 };
265}
266
267impl_node_for_tuple! {
268 (T0,)
269 (T0,T1)
270 (T0,T1,T2)
271 (T0,T1,T2,T3)
272 (T0,T1,T2,T3,T4)
273 (T0,T1,T2,T3,T4,T5)
274 (T0,T1,T2,T3,T4,T5,T6)
275 (T0,T1,T2,T3,T4,T5,T6,T7)
276 (T0,T1,T2,T3,T4,T5,T6,T7,T8)
277 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9)
278 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)
279 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)
280 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12)
281 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13)
282 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14)
283 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15)
284 (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16)
285}
286
287impl<N: Node> Node for Box<N> {
288 #[inline]
289 fn to_node(&self) -> AnyNode {
290 self.as_ref().to_node()
291 }
292 #[inline]
293 fn to_children(&self) -> Option<Children> {
294 self.as_ref().to_children()
295 }
296 #[inline]
297 fn into_node(self) -> AnyNode {
298 (*self).into_node()
299 }
300 #[inline]
301 fn into_children(self) -> Option<Children> {
302 (*self).into_children()
303 }
304}
305
306impl<N: ?Sized + Node> Node for &N {
307 #[inline]
308 fn to_node(&self) -> AnyNode {
309 (*self).to_node()
310 }
311
312 #[inline]
313 fn to_children(&self) -> Option<Children> {
314 (*self).to_children()
315 }
316}