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
use core::iter::FromIterator;

pub trait Chain: Sized {
    type Item;
    type IntoIter: IntoIterator<Item=Self::Item>;
    fn into_iter_chain(self) -> <Self::IntoIter as IntoIterator>::IntoIter;
    fn collect<T: FromIterator<Self::Item>>(self) -> T { self.into_iter_chain().collect() }
    fn as_slice(&self) -> &[Self::Item];
}

impl<T> Chain for Vec<T> {
    type Item = T;
    type IntoIter = <Self as IntoIterator>::IntoIter;
    fn into_iter_chain(self) -> <Self::IntoIter as IntoIterator>::IntoIter { IntoIterator::into_iter(self) }
    fn as_slice(&self) -> &[Self::Item] { &self }
}

pub struct Single<T>([T; 1]);

impl<T> From<T> for Single<T> {
    fn from(item: T) -> Self {
        Self([item])
    }
}

impl<T> IntoIterator for Single<T> {
    type Item = T;
    type IntoIter = SingleIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        let [inner] = self.0;
        SingleIter(Some(inner))
    }
}

impl<T> Chain for Single<T> {
    type Item = T;
    type IntoIter = <Self as IntoIterator>::IntoIter;
    fn into_iter_chain(self) -> <Self::IntoIter as IntoIterator>::IntoIter { IntoIterator::into_iter(self) }
    fn as_slice(&self) -> &[Self::Item] { &self.0 }
}

pub struct SingleIter<T>(Option<T>);

impl<T> Iterator for SingleIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.take()
    }
}

pub trait IntoChain {
    type Item;
    type Chain: Chain<Item=Self::Item>;

    fn into_chain(self) -> Self::Chain;
}

impl<U: Chain> IntoChain for U {
    type Item = U::Item;
    type Chain = Self;
    fn into_chain(self) -> Self::Chain { self }
}

impl<T> IntoChain for Option<T> {
    type Item = T;
    type Chain = OptionChain<T>;

    fn into_chain(self) -> Self::Chain {
        OptionChain(self.map(|item| [item]))
    }
}

pub struct OptionChain<T>(Option<[T; 1]>);

impl<T> Chain for OptionChain<T> {
    type Item = T;
    type IntoIter = <Self as IntoIterator>::IntoIter;
    fn into_iter_chain(self) -> <Self::IntoIter as IntoIterator>::IntoIter { IntoIterator::into_iter(self) }
    fn as_slice(&self) -> &[Self::Item] {
        self.0.as_ref().map(|arr| arr.as_ref()).unwrap_or(&[])
    }
}

impl<T> IntoIterator for OptionChain<T> {
    type Item = T;
    type IntoIter = SingleIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.map(|[inner]| {
            SingleIter(Some(inner))
        }).unwrap_or_else(|| SingleIter(None))
    }
}