hybrid_array/
iter.rs

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//! Support for constructing arrays using a provided iterator function and other iterator-related
//! functionality.

use crate::{Array, ArraySize};
use core::{
    fmt,
    mem::size_of,
    slice::{Iter, IterMut},
};

/// Couldn't construct an array from an iterator because the number of items in the iterator
/// didn't match the array size.
#[derive(Clone, Copy, Debug)]
pub struct TryFromIteratorError;

impl fmt::Display for TryFromIteratorError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("iterator did not contain the correct number of items for the array size")
    }
}

impl core::error::Error for TryFromIteratorError {}

impl<T, U> Array<T, U>
where
    U: ArraySize,
{
    /// Construct an array from the given iterator, returning [`TryFromIteratorError`] in the event
    /// that the number of items in the iterator does not match the array size.
    ///
    /// # Errors
    ///
    /// Returns [`TryFromIteratorError`] in the event the iterator does not return a number of
    /// items which is exactly equal to the array size.
    pub fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, TryFromIteratorError> {
        let mut iter = iter.into_iter();
        let ret = Self::try_from_fn(|_| iter.next().ok_or(TryFromIteratorError))?;

        match iter.next() {
            None => Ok(ret),
            Some(_) => Err(TryFromIteratorError),
        }
    }
}

impl<T, U> FromIterator<T> for Array<T, U>
where
    U: ArraySize,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut iter = iter.into_iter();
        let ret = Self::from_fn(|_| {
            iter.next()
                .expect("iterator should have enough items to fill array")
        });

        assert!(
            iter.next().is_none(),
            "too many items in iterator to fit in array"
        );

        ret
    }
}

impl<T, U> IntoIterator for Array<T, U>
where
    U: ArraySize,
{
    type Item = T;
    type IntoIter = <U::ArrayType<T> as IntoIterator>::IntoIter;

    /// Creates a consuming iterator, that is, one that moves each value out of the array (from
    /// start to end).
    ///
    /// The array cannot be used after calling this unless `T` implements `Copy`, so the whole
    /// array is copied.
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<'a, T, U> IntoIterator for &'a Array<T, U>
where
    U: ArraySize,
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    #[inline]
    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<'a, T, U> IntoIterator for &'a mut Array<T, U>
where
    U: ArraySize,
{
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    #[inline]
    fn into_iter(self) -> IterMut<'a, T> {
        self.iter_mut()
    }
}

impl<T, U, V> Array<Array<T, U>, V>
where
    U: ArraySize,
    V: ArraySize,
{
    /// Takes a `&mut Array<Array<T, N>,M>`, and flattens it to a `&mut [T]`.
    ///
    /// # Panics
    ///
    /// This panics if the length of the resulting slice would overflow a `usize`.
    ///
    /// This is only possible when flattening a slice of arrays of zero-sized
    /// types, and thus tends to be irrelevant in practice. If
    /// `size_of::<T>() > 0`, this will never panic.
    ///
    /// # Examples
    ///
    /// ```
    /// use hybrid_array::{Array, typenum::U3};
    ///
    /// fn add_5_to_all(slice: &mut [i32]) {
    ///     for i in slice {
    ///         *i += 5;
    ///     }
    /// }
    ///
    /// let mut array: Array<Array<i32, U3>, U3> = Array([Array([1_i32, 2, 3]), Array([4, 5, 6]), Array([7, 8, 9])]);
    /// add_5_to_all(array.as_flattened_mut());
    /// assert_eq!(array, Array([Array([6, 7, 8]), Array([9, 10, 11]), Array([12, 13, 14])]));
    /// ```
    pub fn as_flattened_mut(&mut self) -> &mut [T] {
        let len = if size_of::<T>() == 0 {
            self.len()
                .checked_mul(U::USIZE)
                .expect("slice len overflow")
        } else {
            // SAFETY: `self.len() * N` cannot overflow because `self` is
            // already in the address space.
            unsafe { self.len().unchecked_mul(U::USIZE) }
        };
        // SAFETY: `[T]` is layout-identical to `[T; U]`
        unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr().cast(), len) }
    }

    /// Takes a `&Array<Array<T, N>, >>`, and flattens it to a `&[T]`.
    ///
    /// # Panics
    ///
    /// This panics if the length of the resulting slice would overflow a `usize`.
    ///
    /// This is only possible when flattening a slice of arrays of zero-sized
    /// types, and thus tends to be irrelevant in practice. If
    /// `size_of::<T>() > 0`, this will never panic.
    ///
    /// # Examples
    ///
    /// ```
    /// use hybrid_array::{Array, typenum::{U0, U2, U3, U5, U10}};
    ///
    /// let a: Array<Array<usize, U3>, U2> = Array([Array([1, 2, 3]), Array([4, 5, 6])]);
    /// assert_eq!(a.as_flattened(), &[1, 2, 3, 4, 5, 6]);
    ///
    /// let b: Array<Array<usize, U2>, U3> = Array([Array([1, 2]), Array([3, 4]), Array([5, 6])]);
    /// assert_eq!(a.as_flattened(), b.as_flattened());
    ///
    /// let c: Array<[usize; 2], U3> = Array([[1, 2], [3, 4], [5, 6]]);
    /// assert_eq!(a.as_flattened(), c.as_flattened());
    ///
    /// let slice_of_empty_arrays: &Array<Array<i32, U5>, U0> = &Array::from_fn(|_| Array([1, 2, 3, 4, 5]));
    /// assert!(slice_of_empty_arrays.as_flattened().is_empty());
    ///
    /// let empty_slice_of_arrays: &Array<Array<u32, U10>, U0>  = &Array([]);
    /// assert!(empty_slice_of_arrays.as_flattened().is_empty());
    /// ```
    pub fn as_flattened(&self) -> &[T] {
        let len = if size_of::<T>() == 0 {
            self.len()
                .checked_mul(U::USIZE)
                .expect("slice len overflow")
        } else {
            // SAFETY: `self.len() * N` cannot overflow because `self` is
            // already in the address space.
            unsafe { self.len().unchecked_mul(U::USIZE) }
        };
        // SAFETY: `[T]` is layout-identical to `[T; U]`
        unsafe { core::slice::from_raw_parts(self.as_ptr().cast(), len) }
    }
}