Skip to main content

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}