Skip to main content

virtual_node/
iterable_nodes.rs

1use crate::event::RealDom;
2use crate::{View, VirtualNode};
3
4/// Used by the html! macro for all braced child nodes so that we can use any type
5/// that implements Into<IterableNodes>
6///
7/// html! { <div> { nodes } </div> }
8///
9/// nodes can be a String .. VirtualNode .. Vec<VirtualNode> ... etc
10pub struct IterableNodes<Handle: RealDom>(Vec<VirtualNode<Handle>>);
11
12impl<Handle: RealDom> IterableNodes<Handle> {
13    /// Retrieve the first node mutably
14    pub fn first_mut(&mut self) -> Option<&mut VirtualNode<Handle>> {
15        self.0.first_mut()
16    }
17
18    /// Retrieve the last node mutably
19    pub fn last_mut(&mut self) -> Option<&mut VirtualNode<Handle>> {
20        self.0.last_mut()
21    }
22}
23
24impl<Handle: RealDom> IntoIterator for IterableNodes<Handle> {
25    type Item = VirtualNode<Handle>;
26    // TODO: Is this possible with an array [VirtualNode] instead of a vec?
27    type IntoIter = ::std::vec::IntoIter<VirtualNode<Handle>>;
28
29    fn into_iter(self) -> Self::IntoIter {
30        self.0.into_iter()
31    }
32}
33
34impl<Handle: RealDom> From<VirtualNode<Handle>> for IterableNodes<Handle> {
35    fn from(other: VirtualNode<Handle>) -> Self {
36        IterableNodes(vec![other])
37    }
38}
39
40impl<Handle: RealDom> From<&str> for IterableNodes<Handle> {
41    fn from(other: &str) -> Self {
42        IterableNodes(vec![VirtualNode::new_text(other)])
43    }
44}
45
46impl<Handle: RealDom> From<String> for IterableNodes<Handle> {
47    fn from(other: String) -> Self {
48        IterableNodes(vec![VirtualNode::new_text(other.as_str())])
49    }
50}
51
52impl<Handle: RealDom> From<&String> for IterableNodes<Handle> {
53    fn from(other: &String) -> Self {
54        IterableNodes(vec![VirtualNode::new_text(other.as_str())])
55    }
56}
57
58impl<Handle: RealDom> From<Vec<VirtualNode<Handle>>> for IterableNodes<Handle> {
59    fn from(other: Vec<VirtualNode<Handle>>) -> Self {
60        IterableNodes(other)
61    }
62}
63
64#[cfg(feature = "web")]
65impl<V: View<web_sys::Window>> From<V> for IterableNodes<web_sys::Window> {
66    fn from(from: V) -> Self {
67        IterableNodes(vec![from.render()])
68    }
69}
70
71impl<T: Into<IterableNodes<Handle>>, Handle: RealDom> From<Option<T>> for IterableNodes<Handle> {
72    fn from(opt: Option<T>) -> Self {
73        if let Some(val) = opt {
74            val.into()
75        } else {
76            IterableNodes(vec![])
77        }
78    }
79}
80
81#[cfg(feature = "web")]
82impl<V: View<web_sys::Window>> From<Vec<V>> for IterableNodes<web_sys::Window> {
83    fn from(other: Vec<V>) -> Self {
84        IterableNodes(other.into_iter().map(|it| it.render()).collect())
85    }
86}
87
88impl<V: View<Handle>, Handle: RealDom> From<&Vec<V>> for IterableNodes<Handle> {
89    fn from(other: &Vec<V>) -> Self {
90        IterableNodes(other.iter().map(|it| it.render()).collect())
91    }
92}
93
94impl<V: View<Handle>, Handle: RealDom> From<&[V]> for IterableNodes<Handle> {
95    fn from(other: &[V]) -> Self {
96        IterableNodes(other.iter().map(|it| it.render()).collect())
97    }
98}
99
100// Implements
101//   From<T> and From<&T> -> IterableNodes
102//   by using T's Display implementation.
103macro_rules! from_display_impls {
104    ($ty:ty) => {
105        impl<Handle: RealDom> From<$ty> for IterableNodes<Handle> {
106            fn from(val: $ty) -> Self {
107                IterableNodes::from(val.to_string())
108            }
109        }
110
111        impl<Handle: RealDom> From<&$ty> for IterableNodes<Handle> {
112            fn from(val: &$ty) -> Self {
113                IterableNodes::from(val.to_string())
114            }
115        }
116    };
117
118    ($ty:ty, $($tys:ty),*) => {
119        from_display_impls!( $ty );
120        from_display_impls! ( $($tys),* );
121    }
122}
123from_display_impls!(u8, u16, u32, usize, u64, u128, i8, i16, i32, isize, i64, i128, f32, f64);