use super::Id;
use crate::mutability::{IsAllocableAnyThread, IsMutable};
pub trait DefaultId: IsAllocableAnyThread {
fn default_id() -> Id<Self>;
}
impl<T: ?Sized + DefaultId> Default for Id<T> {
#[inline]
fn default() -> Self {
T::default_id()
}
}
pub trait IdIntoIterator {
type Item;
type IntoIter: Iterator<Item = Self::Item>;
fn id_into_iter(this: Id<Self>) -> Self::IntoIter;
}
impl<T: ?Sized + IdIntoIterator> IntoIterator for Id<T> {
type Item = <T as IdIntoIterator>::Item;
type IntoIter = <T as IdIntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
T::id_into_iter(self)
}
}
impl<'a, T: ?Sized> IntoIterator for &'a Id<T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(&**self).into_iter()
}
}
impl<'a, T: ?Sized + IsMutable> IntoIterator for &'a mut Id<T>
where
&'a mut T: IntoIterator,
{
type Item = <&'a mut T as IntoIterator>::Item;
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(&mut **self).into_iter()
}
}
pub trait IdFromIterator<T>: Sized {
fn id_from_iter<I>(iter: I) -> Id<Self>
where
I: IntoIterator<Item = T>;
}
impl<T, U: IdFromIterator<T>> FromIterator<T> for Id<U> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
U::id_from_iter(iter)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mutability::Mutable;
use crate::runtime::NSObject;
use crate::{declare_class, msg_send_id, ClassType};
declare_class!(
#[derive(PartialEq, Eq, Hash, Debug)]
struct Collection;
unsafe impl ClassType for Collection {
type Super = NSObject;
type Mutability = Mutable;
const NAME: &'static str = "MyCustomCollection";
}
);
impl DefaultId for Collection {
fn default_id() -> Id<Self> {
unsafe { msg_send_id![Collection::class(), new] }
}
}
struct Iter<'a>(&'a Collection);
impl<'a> Iterator for Iter<'a> {
type Item = &'a NSObject;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl<'a> IntoIterator for &'a Collection {
type Item = &'a NSObject;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
Iter(self)
}
}
struct IterMut<'a>(&'a mut Collection);
impl<'a> Iterator for IterMut<'a> {
type Item = &'a mut NSObject;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl<'a> IntoIterator for &'a mut Collection {
type Item = &'a mut NSObject;
type IntoIter = IterMut<'a>;
fn into_iter(self) -> Self::IntoIter {
IterMut(self)
}
}
struct IntoIter(Id<Collection>);
impl Iterator for IntoIter {
type Item = Id<NSObject>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl IdIntoIterator for Collection {
type Item = Id<NSObject>;
type IntoIter = IntoIter;
fn id_into_iter(this: Id<Self>) -> Self::IntoIter {
IntoIter(this)
}
}
impl IdFromIterator<Id<NSObject>> for Collection {
fn id_from_iter<I: IntoIterator<Item = Id<NSObject>>>(_iter: I) -> Id<Self> {
Collection::default_id()
}
}
#[test]
fn test_default() {
let obj1: Id<Collection> = Default::default();
let obj2 = Collection::default_id();
assert_ne!(obj1, obj2);
}
#[test]
fn test_into_iter() {
let mut obj: Id<Collection> = Default::default();
for _ in &*obj {}
for _ in &obj {}
for _ in &mut *obj {}
for _ in &mut obj {}
for _ in obj {}
}
#[test]
fn test_from_iter() {
let _: Id<Collection> = [NSObject::new()].into_iter().collect();
}
}