1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
//! Base iterator traits.

cfg_if! {
    if #[cfg(feature = "std")] {
        use std::iter::FromIterator;
    } else {
        use core::iter::FromIterator;
    }
}

use refs::{Ref, RefMut};

/// A trait for iterable collections which contain data of a given type.
///
/// In most cases, you shouldn't implement this trait directly; instead, you should implement
/// `IntoIterator`, which will in turn implement this trait.
///
/// The only exception is dynamically-sized types, which cannot implement `IntoIterator`. Instead,
/// you should implement this trait to indicate what type of data is inside the collection.
pub trait HasData {
    /// The type of the data inside this collection.
    type Item;
}
impl<T: IntoIterator> HasData for T {
    type Item = <T as IntoIterator>::Item;
}

/// A trait for collections which can be iterated by reference.
///
/// In most cases, you shouldn't implement this trait directly; instead, you should implement
/// `IntoIterator` for a reference of this type, which will in turn implement this trait.
pub trait Iter<'a>: 'a + HasData {
    /// Type of the references to the data in the collection.
    ///
    /// Although this might just be `&'a Item`, it can also be more complicated. For example, an
    /// iterator with `Item = (usize, T)` might use `(usize, &'a T)` for this instead.
    ///
    /// For more information, see the `Ref` trait.
    type ItemRef: Ref<'a, Self::Item>;

    /// Type of the iterator over references.
    type IterRef: Iterator<Item = Self::ItemRef>;

    /// Constructs an iterator over references to the data in this collection.
    fn iter(&'a self) -> Self::IterRef;
}
impl<'a, T: 'a + HasData> Iter<'a> for T
where
    &'a T: IntoIterator,
    <&'a T as IntoIterator>::Item: Ref<'a, T::Item>,
{
    type ItemRef = <&'a Self as IntoIterator>::Item;
    type IterRef = <&'a Self as IntoIterator>::IntoIter;
    fn iter(&'a self) -> Self::IterRef {
        self.into_iter()
    }
}

/// A trait for collections which can be iterated by mutable reference.
///
/// In most cases, you shouldn't implement this trait directly; instead, you should implement
/// `IntoIterator` for a mutable reference of this type, which will in turn implement this trait.
pub trait IterMut<'a>: Iter<'a> {
    /// Type of the mutable references to the data in the collection.
    ///
    /// Although this might just be `&'a Item`, it can also be more complicated. For example, an
    /// iterator with `Item = (usize, T)` might use `(usize, &'a mut T)` for this instead.
    ///
    /// For more information, see the `RefMut` trait.
    type ItemMut: RefMut<'a, Self::Item>;

    /// Type of the iterator over mutable references.
    type IterMut: Iterator<Item = Self::ItemMut>;

    /// Constructs an iterator over mutable references to the data in this collection.
    fn iter_mut(&'a mut self) -> Self::IterMut;
}
impl<'a, T: 'a + Iter<'a>> IterMut<'a> for T
where
    &'a mut T: IntoIterator,
    <&'a mut T as IntoIterator>::Item: RefMut<'a, T::Item>,
{
    type ItemMut = <&'a mut Self as IntoIterator>::Item;
    type IterMut = <&'a mut Self as IntoIterator>::IntoIter;
    fn iter_mut(&'a mut self) -> Self::IterMut {
        self.into_iter()
    }
}

/// A trait for collections which can be converted to and from iterators over data.
pub trait IterOwned
    : HasData
    + IntoIterator<Item = <Self as HasData>::Item>
    + FromIterator<<Self as HasData>::Item>
    + Extend<<Self as HasData>::Item>
{}
impl<T> IterOwned for T
where
    T: HasData,
    T: IntoIterator<Item = <T as HasData>::Item>,
    T: FromIterator<<T as HasData>::Item>,
    T: Extend<<T as HasData>::Item>,
{}