floem/view/into_iter.rs
1//! Trait for converting various types into an iterator of views.
2//!
3//! The [`IntoViewIter`] trait provides a unified way to convert arrays, tuples,
4//! vectors, slices, and iterators into an iterator of views.
5//!
6//! # Supported Types
7//!
8//! | Type | Example |
9//! |------|---------|
10//! | Arrays `[V; N]` | `[label("a"), label("b")]` |
11//! | Tuples (1-16) | `(label("a"), button("b"), "text")` |
12//! | `Vec<V>` | `vec![label("a"), label("b")]` |
13//! | Slices `&[V]` | `&items[..]` (requires `V: Clone`) |
14//! | Empty `()` | `()` |
15//! | Iterator | `iter.map(label).collect::<Vec<_>>()` |
16//!
17//! # Example
18//!
19//! ```rust
20//! use floem::prelude::*;
21//!
22//! // Using the trait to iterate over children
23//! fn process_children(children: impl IntoViewIter) {
24//! for view in children.into_view_iter() {
25//! // Each `view` is an AnyView (Box<dyn View>)
26//! println!("View id: {:?}", view.id());
27//! }
28//! }
29//!
30//! // Can be called with various types:
31//! // process_children([label("a"), label("b")]); // array
32//! // process_children((label("a"), button("b"))); // tuple
33//! // process_children(vec![label("a"), label("b")]); // vec
34//! // process_children(items.iter().map(label).collect::<Vec<_>>()); // iterator
35//! ```
36
37use super::{AnyView, IntoView};
38
39/// Trait for types that can be converted into an iterator of views.
40///
41/// Returns an iterator to enable lazy view construction and avoid intermediate allocations.
42pub trait IntoViewIter {
43 /// Converts this type into an iterator of boxed views.
44 fn into_view_iter(self) -> impl Iterator<Item = AnyView>;
45}
46
47// =============================================================================
48// Arrays: [V; N] where V: IntoView (homogeneous types, compile-time size)
49// =============================================================================
50
51impl<V: IntoView, const N: usize> IntoViewIter for [V; N] {
52 fn into_view_iter(self) -> impl Iterator<Item = AnyView> {
53 self.into_iter().map(|v| v.into_any())
54 }
55}
56
57// =============================================================================
58// Vec<V> where V: IntoView (homogeneous types, dynamic size)
59// =============================================================================
60
61impl<V: IntoView> IntoViewIter for Vec<V> {
62 fn into_view_iter(self) -> impl Iterator<Item = AnyView> {
63 self.into_iter().map(|v| v.into_any())
64 }
65}
66
67// =============================================================================
68// Slices: &[V] where V: IntoView + Clone
69// =============================================================================
70
71impl<V: IntoView + Clone> IntoViewIter for &[V] {
72 fn into_view_iter(self) -> impl Iterator<Item = AnyView> {
73 self.iter().cloned().map(|v| v.into_any())
74 }
75}
76
77// =============================================================================
78// Empty tuple
79// =============================================================================
80
81impl IntoViewIter for () {
82 fn into_view_iter(self) -> impl Iterator<Item = AnyView> {
83 std::iter::empty()
84 }
85}
86
87// =============================================================================
88// Tuples via macro (heterogeneous types)
89// =============================================================================
90
91macro_rules! impl_into_view_iter_for_tuple {
92 ($($t:ident),+; $($idx:tt),+) => {
93 impl<$($t: IntoView),+> IntoViewIter for ($($t,)+) {
94 fn into_view_iter(self) -> impl Iterator<Item = AnyView> {
95 [$(self.$idx.into_any()),+].into_iter()
96 }
97 }
98 };
99}
100
101impl_into_view_iter_for_tuple!(A; 0);
102impl_into_view_iter_for_tuple!(A, B; 0, 1);
103impl_into_view_iter_for_tuple!(A, B, C; 0, 1, 2);
104impl_into_view_iter_for_tuple!(A, B, C, D; 0, 1, 2, 3);
105impl_into_view_iter_for_tuple!(A, B, C, D, E; 0, 1, 2, 3, 4);
106impl_into_view_iter_for_tuple!(A, B, C, D, E, F; 0, 1, 2, 3, 4, 5);
107impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G; 0, 1, 2, 3, 4, 5, 6);
108impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H; 0, 1, 2, 3, 4, 5, 6, 7);
109impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I; 0, 1, 2, 3, 4, 5, 6, 7, 8);
110impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
111impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
112impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
113impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
114impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
115impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
116impl_into_view_iter_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 // Type-level tests to ensure the trait is implemented correctly
123 fn _assert_into_view_iter<T: IntoViewIter>() {}
124
125 fn _test_impls() {
126 // Arrays
127 _assert_into_view_iter::<[(); 0]>();
128 _assert_into_view_iter::<[(); 1]>();
129 _assert_into_view_iter::<[(); 5]>();
130
131 // Tuples
132 _assert_into_view_iter::<()>();
133 _assert_into_view_iter::<((),)>();
134 _assert_into_view_iter::<((), ())>();
135 _assert_into_view_iter::<((), (), ())>();
136
137 // Vec
138 _assert_into_view_iter::<Vec<()>>();
139
140 // Slices
141 _assert_into_view_iter::<&[()]>();
142
143 // Vec<AnyView>
144 _assert_into_view_iter::<Vec<AnyView>>();
145 }
146}