tachys/view/
fragment.rs

1use super::{
2    any_view::{AnyView, IntoAny},
3    iterators::StaticVec,
4};
5use crate::html::element::HtmlElement;
6
7/// A typed-erased collection of different views.
8pub struct Fragment {
9    /// The nodes contained in the fragment.
10    pub nodes: StaticVec<AnyView>,
11}
12
13/// Converts some view into a type-erased collection of views.
14pub trait IntoFragment {
15    /// Converts some view into a type-erased collection of views.
16    fn into_fragment(self) -> Fragment;
17}
18
19impl FromIterator<AnyView> for Fragment {
20    fn from_iter<T: IntoIterator<Item = AnyView>>(iter: T) -> Self {
21        Fragment::new(iter.into_iter().collect())
22    }
23}
24
25impl From<AnyView> for Fragment {
26    fn from(view: AnyView) -> Self {
27        Fragment::new(vec![view])
28    }
29}
30
31impl From<Fragment> for AnyView {
32    fn from(value: Fragment) -> Self {
33        value.nodes.into_any()
34    }
35}
36
37impl Fragment {
38    /// Creates a new [`Fragment`].
39    #[inline(always)]
40    pub fn new(nodes: Vec<AnyView>) -> Self {
41        Self {
42            nodes: nodes.into(),
43        }
44    }
45}
46
47impl<E, At, Ch> IntoFragment for HtmlElement<E, At, Ch>
48where
49    HtmlElement<E, At, Ch>: IntoAny,
50{
51    fn into_fragment(self) -> Fragment {
52        Fragment::new(vec![self.into_any()])
53    }
54}
55
56impl IntoFragment for AnyView {
57    fn into_fragment(self) -> Fragment {
58        Fragment::new(vec![self])
59    }
60}
61
62impl<T> IntoFragment for Vec<T>
63where
64    T: IntoAny,
65{
66    fn into_fragment(self) -> Fragment {
67        Fragment::new(self.into_iter().map(IntoAny::into_any).collect())
68    }
69}
70
71impl<T> IntoFragment for StaticVec<T>
72where
73    T: IntoAny,
74{
75    fn into_fragment(self) -> Fragment {
76        Fragment::new(self.into_iter().map(IntoAny::into_any).collect())
77    }
78}
79
80impl<const N: usize, T> IntoFragment for [T; N]
81where
82    T: IntoAny,
83{
84    fn into_fragment(self) -> Fragment {
85        Fragment::new(self.into_iter().map(IntoAny::into_any).collect())
86    }
87}
88
89macro_rules! tuples {
90	($($ty:ident),*) => {
91		impl<$($ty),*> IntoFragment for ($($ty,)*)
92		where
93			$($ty: IntoAny),*,
94
95		{
96            fn into_fragment(self) -> Fragment {
97                #[allow(non_snake_case)]
98			    let ($($ty,)*) = self;
99                Fragment::new(vec![$($ty.into_any(),)*])
100            }
101        }
102    }
103}
104
105tuples!(A);
106tuples!(A, B);
107tuples!(A, B, C);
108tuples!(A, B, C, D);
109tuples!(A, B, C, D, E);
110tuples!(A, B, C, D, E, F);
111tuples!(A, B, C, D, E, F, G);
112tuples!(A, B, C, D, E, F, G, H);
113tuples!(A, B, C, D, E, F, G, H, I);
114tuples!(A, B, C, D, E, F, G, H, I, J);
115tuples!(A, B, C, D, E, F, G, H, I, J, K);
116tuples!(A, B, C, D, E, F, G, H, I, J, K, L);
117tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M);
118tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
119tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
120tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
121tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
122tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
123tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
124tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
125tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
126tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
127tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
128tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
129tuples!(
130    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
131);
132tuples!(
133    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y,
134    Z
135);