Closed
Description
The way we do NSEnumerator
and NSFastEnumeration
right now is a mess!
Ideally, I don't think NSEnumerator
should have a lifetime (it would allow it to be treated normally in icrate
). This means that any method that creates an NSEnumerator
is inherently unsafe
, but instead I think we should just create proper methods and Iterator
wrappers where applicable.
Rough sketches below. Note that the iterator must sometimes hold a reference to the array, since otherwise the array could be modified. Luckily the returned items can have the same lifetime as the array (instead of e.g. the same lifetime as the iterator).
impl<T, O> NSArray<T, O> {
fn iter<'a>(&'a self) -> impl Iterator<&'a T> + 'a;
}
impl<T> NSArray<T, Owned> {
fn iter_mut<'a>(&'a mut self) -> impl Iterator<&'a mut T> + 'a;
}
impl<T> NSArray<T, Shared> {
// While the items are immutable, the array may not be, so we still need to bind the lifetime of the iterator to the array
fn iter_retained<'a>(&'a self) -> impl Iterator<Id<T, Shared>> + '_;
// But here we know that the array is immutable, so with this design we wouldn't need to
fn iter_retained2(this: &Id<Self, Shared>) -> impl Iterator<Id<T, Shared>>;
}
impl<T, O> NSArray<T, O> {
fn into_iter(this: Id<Self, O>) -> impl Iterator<Id<T, O>>;
}
// Or perhaps ideally:
// impl<T> NSArray<T, Shared> {
// fn into_iter(this: Id<Self, Owned>) -> impl Iterator<Id<T, Shared>>;
// fn into_iter(this: Id<Self, Shared>) -> impl Iterator<Id<T, Shared>>;
// }
// impl<T> NSArray<T, Owned> {
// fn into_iter(this: Id<Self, Owned>) -> impl Iterator<Id<T, Owned>>;
// fn into_iter(this: Id<Self, Shared>) -> impl Iterator<Id<T, Shared>>;
// }
impl<K, V, KO, VO> NSDictionary<K, V, KO, VO> {
fn iter_keys<'a>(&'a self) -> impl Iterator<&'a K> + 'a;
fn iter_values<'a>(&'a self) -> impl Iterator<&'a V> + 'a;
fn iter<'a>(&'a self) -> impl Iterator<(&'a K, &'a V)> + 'a {
std::iter::zip(self.iter_keys(), self.iter_values())
}
}
impl<K, V, VO> NSDictionary<K, V, Owned, VO> {
fn iter_keys_mut<'a>(&'a mut self) -> impl Iterator<&'a mut K> + 'a;
}
impl<K, V, KO> NSDictionary<K, V, KO, Owned> {
fn iter_values_mut<'a>(&'a mut self) -> impl Iterator<&'a mut V> + 'a;
}
impl<K, V, VO> NSDictionary<K, V, Shared, VO> {
fn iter_keys_retained<'a>(&'a self) -> impl Iterator<Id<K, Shared>> + 'a;
fn iter_keys_retained2(this: &Id<Self, Shared>) -> impl Iterator<Id<K, Shared>>;
}
// And so on...
// Unsure if the following is possible?
impl<K, V> NSDictionary<K, V, Owned, Owned> {
fn iter_mut<'a>(&'a mut self) -> impl Iterator<(&'a mut K, &'a mut V)> + 'a;
}
// And maybe more vairants that return
// - (&'a K, &'a mut V)
// - (&'a mut K, &'a V)
// - (&'a mut K, Id<V, Shared>)
// - ...
See also #29 (comment)