checs/
iter.rs

1//! Iterating over entities and queries.
2
3use sealed::{Bounds, Sealed};
4
5mod sealed {
6    pub trait Sealed: Sized {}
7    pub struct Bounds<T>(T);
8    impl<T> Sealed for Bounds<T> {}
9}
10
11/// Provides the associated item for [`LendingIterator`], similar to [`Iterator::Item`].
12///
13/// See [`LendingIterator`] for more.
14pub trait Lifetime<'a, ImplicitBounds: Sealed = Bounds<&'a Self>> {
15    /// The type of the elements being iterated over.
16    type Item;
17}
18
19/// A trait similar to [`Iterator`], where the returned [`Item`]s only live until [`next`] is
20/// called again.
21///
22/// See also: <https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats>
23///
24/// # Examples
25///
26/// Unlike the regular [`Iterator`]s the `LendingIterator` does not support `for` loops. A `while
27/// let` loop can be used instead:
28///
29/// ```
30/// # use checs::{Lifetime, LendingIterator};
31/// # struct Empty;
32/// # impl Lifetime<'_> for Empty {
33/// #     type Item = ();
34/// # }
35/// # impl LendingIterator for Empty {
36/// #     fn next(&mut self) -> Option<()> {
37/// #         None
38/// #     }
39/// # }
40/// # let mut iter = Empty;
41/// while let Some(item) = iter.next() {
42///     println!("{item:?}");
43/// }
44/// ```
45///
46/// See [`Query`] for more examples, since it is the only type currently implementing `LendingIterator`.
47///
48/// [`next`]: LendingIterator::next
49/// [`Item`]: Lifetime::Item
50/// [`Query`]: crate::Query
51#[must_use = "iterators are lazy and do nothing unless consumed"]
52pub trait LendingIterator: for<'a> Lifetime<'a> {
53    /// Advances the iterator and returns the next value.
54    ///
55    /// The value's lifetime ends before `next` is called again.
56    fn next(&mut self) -> Option<<Self as Lifetime<'_>>::Item>;
57
58    /// Calls a closure on each element of the iterator.
59    ///
60    /// This is an alternative to using a `LendingIterator` in a `while let` loop.
61    ///
62    /// # Examples
63    ///
64    /// See [`Query`] for more examples, since it is the only type currently implementing
65    /// `LendingIterator`.
66    ///
67    /// [`Query`]: crate::Query
68    ///
69    /// ```
70    /// use checs::{ComponentVec, IntoQuery, LendingIterator};
71    ///
72    /// let ints: ComponentVec<i32> = ComponentVec::new();
73    /// let mut floats: ComponentVec<f32> = ComponentVec::new();
74    ///
75    /// let query = (&ints, &mut floats).into_query();
76    ///
77    /// query.for_each(|(entity, (int, float))| {
78    ///     println!("{entity:?}: ({int}, {float})");
79    /// });
80    /// ```
81    #[inline]
82    fn for_each<F>(mut self, mut f: F)
83    where
84        Self: Sized,
85        F: FnMut(<Self as Lifetime>::Item),
86    {
87        while let Some(item) = self.next() {
88            f(item);
89        }
90    }
91}
92
93/// An iterator over a slice that copies its values.
94pub type Iter<'a, T> = std::iter::Copied<std::slice::Iter<'a, T>>;
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn iter_as_iterator() {
102        let numbers = [42, 17, 99];
103        let mut it: Iter<_> = numbers.iter().copied();
104
105        assert_eq!(Iterator::next(&mut it), Some(42));
106        assert_eq!(Iterator::next(&mut it), Some(17));
107        assert_eq!(Iterator::next(&mut it), Some(99));
108        assert_eq!(Iterator::next(&mut it), None);
109    }
110}