objc2_foundation/
enumerator.rs

1//! Utilities for the `NSEnumerator` class.
2use objc2::rc::Retained;
3use objc2::Message;
4
5use crate::{iter, NSEnumerator};
6
7// TODO: Measure whether iterating through `nextObject` or fast enumeration is
8// fastest.
9// impl<ObjectType: Message> Iterator for NSEnumerator<ObjectType> {
10//     type Item = Retained<ObjectType>;
11//
12//     #[inline]
13//     fn next(&mut self) -> Option<Retained<ObjectType>> {
14//         self.nextObject()
15//     }
16// }
17
18impl<ObjectType: Message> NSEnumerator<ObjectType> {
19    /// Iterate over the enumerator's elements.
20    #[inline]
21    pub fn iter(&self) -> Iter<'_, ObjectType> {
22        Iter(iter::Iter::new(self))
23    }
24
25    /// Iterate over the enumerator without retaining the elements.
26    ///
27    /// Consider using the [`iter`](Self::iter) method instead, unless you're
28    /// seeing performance issues from the retaining.
29    ///
30    /// # Safety
31    ///
32    /// The enumerator and the underlying collection must not be mutated while
33    /// the iterator is alive.
34    #[inline]
35    pub unsafe fn iter_unchecked(&self) -> IterUnchecked<'_, ObjectType> {
36        IterUnchecked(iter::IterUnchecked::new(self))
37    }
38}
39
40unsafe impl<ObjectType: Message> iter::FastEnumerationHelper for NSEnumerator<ObjectType> {
41    type Item = ObjectType;
42
43    #[inline]
44    fn maybe_len(&self) -> Option<usize> {
45        None
46    }
47}
48
49/// An iterator over the items in an enumerator.
50#[derive(Debug)]
51pub struct Iter<'a, ObjectType: Message>(iter::Iter<'a, NSEnumerator<ObjectType>>);
52
53__impl_iter! {
54    impl<'a, ObjectType: Message> Iterator<Item = Retained<ObjectType>> for Iter<'a, ObjectType> { ... }
55}
56
57/// An iterator over unretained items in an enumerator.
58///
59/// # Safety
60///
61/// The enumerator and the underlying collection must not be mutated while
62/// this is alive.
63#[derive(Debug)]
64pub struct IterUnchecked<'a, ObjectType: Message + 'a>(
65    iter::IterUnchecked<'a, NSEnumerator<ObjectType>>,
66);
67
68__impl_iter! {
69    impl<'a, ObjectType: Message> Iterator<Item = &'a ObjectType> for IterUnchecked<'a, ObjectType> { ... }
70}
71
72/// A consuming iterator over the items in an enumerator.
73#[derive(Debug)]
74pub struct IntoIter<ObjectType: Message>(iter::IntoIter<NSEnumerator<ObjectType>>);
75
76__impl_iter! {
77    impl<ObjectType: Message> Iterator<Item = Retained<ObjectType>> for IntoIter<ObjectType> { ... }
78}
79
80__impl_into_iter! {
81    impl<ObjectType: Message> IntoIterator for &NSEnumerator<ObjectType> {
82        type IntoIter = Iter<'_, ObjectType>;
83    }
84
85    impl<ObjectType: Message> IntoIterator for Retained<NSEnumerator<ObjectType>> {
86        #[uses(new)]
87        type IntoIter = IntoIter<ObjectType>;
88    }
89}
90
91// TODO: Does fast enumeration modify the enumeration while iterating?