itermaps/
utils.rs

1use core::{
2    ops::Deref,
3    pin::Pin,
4};
5
6/// Consume self into reference
7pub trait ThisRef<'a>: 'a {
8    type Out: ?Sized;
9
10    /// Consume self into reference
11    fn this_ref(self) -> &'a Self::Out;
12}
13
14/// Consume self into mutable reference
15pub trait ThisMut<'a>: ThisRef<'a> {
16    /// Consume self into mutable reference
17    fn this_mut(self) -> &'a mut Self::Out;
18}
19impl<'a, T: ?Sized> ThisRef<'a> for &'a T {
20    type Out = T;
21
22    fn this_ref(self) -> &'a Self::Out {
23        self
24    }
25}
26impl<'a, T: ?Sized> ThisRef<'a> for &'a mut T {
27    type Out = T;
28
29    fn this_ref(self) -> &'a Self::Out {
30        self
31    }
32}
33impl<'a, T: ?Sized> ThisMut<'a> for &'a mut T {
34    fn this_mut(self) -> &'a mut Self::Out {
35        self
36    }
37}
38impl<'a, P> ThisRef<'a> for Pin<P>
39where P: Deref + ThisRef<'a>,
40      P::Target: Unpin,
41{
42    type Out = P::Out;
43
44    fn this_ref(self) -> &'a Self::Out {
45        Pin::into_inner(self).this_ref()
46    }
47}
48impl<'a, P> ThisMut<'a> for Pin<P>
49where P: Deref + ThisMut<'a>,
50      P::Target: Unpin,
51{
52    fn this_mut(self) -> &'a mut Self::Out {
53        Pin::into_inner(self).this_mut()
54    }
55}
56
57pub(crate) fn array_each_ref<T, const N: usize>(arr: &[T; N]) -> [&T; N] {
58    use core::mem::{transmute_copy, MaybeUninit};
59    let mut result: [MaybeUninit<&T>; N] = unsafe {
60        MaybeUninit::uninit()
61            .assume_init()
62    };
63    for i in 0..N {
64        result[i].write(&arr[i]);
65    }
66    unsafe { transmute_copy(&result) }
67}
68pub(crate) fn array_each_mut<T, const N: usize>(arr: &mut [T; N]) -> [&mut T; N] {
69    use core::mem::{transmute_copy, MaybeUninit};
70    let mut result: [MaybeUninit<&mut T>; N] = unsafe {
71        MaybeUninit::uninit()
72            .assume_init()
73    };
74    let mut elem;
75    let mut arr = &mut arr[..];
76    #[allow(clippy::needless_range_loop)]
77    for i in 0..N {
78        (elem, arr) = arr.split_first_mut().unwrap();
79        result[i].write(elem);
80    }
81    unsafe { transmute_copy(&result) }
82}
83
84/// Unpack, e.g `&(A, B)` into `(&A, &B)`
85///
86/// # Examples
87/// ```
88/// # use itermaps::Unpack;
89/// let arr: [&i32; 2] = (&[1, 2]).unpack();
90/// assert_eq!(arr, [&1, &2]);
91/// ```
92pub trait Unpack: Sized {
93    type Output;
94
95    /// Unpack, e.g `&(A, B)` into `(&A, &B)`
96    fn unpack(self) -> Self::Output;
97}
98macro_rules! impls1 {
99    (@impl($i:ident) $(
100        $(#[$meta:meta])*
101        $ty:ty $(=[$($g:tt)*]($($w:tt)*))?=> $to:ty
102    ),+ $(,)? $b:block) => {
103        $(
104            $(#[$meta])*
105            impl$(<$($g)*>)? Unpack for $ty
106            $(where $($w)*)?
107            {
108                type Output = $to;
109
110                fn unpack($i) -> $to $b
111            }
112        )+
113    };
114    (@impl($i:ident) $(
115        $(#[$meta:meta])*
116        $ty:ty $(=[$($g:tt)*])?=> $to:ty
117    ),+ $(,)? $b:block) => {
118        $(
119            $(#[$meta])*
120            impl$(<$($g)*>)? Unpack for $ty {
121                type Output = $to;
122
123                fn unpack($i) -> $to $b
124            }
125        )+
126    };
127    ($self:ident {
128        $($(
129            $(#[$meta:meta])*
130            $ty:ty $(=[$($g:tt)*]$(($($w:tt)*))?)?=> $to:ty
131        ),+ $(,)? $b:block)*
132    }) => {
133        $(impls1! {
134            @impl($self)
135            $(
136                $(#[$meta])*
137                $ty $(=[$($g)*]$(($($w)*))?)? => $to
138            ),+ $b
139        })*
140    };
141}
142impls1!(self {
143    &'_ &'a T           =['a, T: ?Sized]    => &'a T,
144    &'_ mut &'a T       =['a, T: ?Sized]    => &'a T,
145    &'a mut &'_ mut T   =['a, T: ?Sized]    => &'a mut T,
146    {
147        *self
148    }
149
150    &'a Option<T>           =['a, T]    => Option<&'a T>,
151    &'a Result<T, E>        =['a, T, E] => Result<&'a T, &'a E>,
152    {
153        self.as_ref()
154    }
155
156    &'a mut Option<T>       =['a, T]    => Option<&'a mut T>,
157    &'a mut Result<T, E>    =['a, T, E] => Result<&'a mut T, &'a mut E>,
158    {
159        self.as_mut()
160    }
161
162    Option<&'a mut T>       =['a, T: ?Sized] => Option<&'a T>,
163    {
164        self.map(|x| &*x)
165    }
166
167    Result<&'a mut T, &'a mut E>    =['a, T: ?Sized, E: ?Sized]
168        => Result<&'a T, &'a E>,
169    {
170        match self {
171            Ok(t) => Ok(t),
172            Err(e) => Err(e),
173        }
174    }
175
176    &'a [T; N]      =['a, T, const N: usize]    => [&'a T; N],
177    {
178        array_each_ref(self)
179    }
180
181    &'a mut [T; N]  =['a, T, const N: usize]    => [&'a mut T; N],
182    {
183        array_each_mut(self)
184    }
185
186    [&'a mut T; N]  =['a, T: ?Sized, const N: usize]    => [&'a T; N],
187    {
188        self.map(|x| &*x)
189    }
190
191    #[cfg(feature = "std")]
192    Box<T>  =[T]    => T,
193    {
194        *self
195    }
196});
197macro_rules! impls2 {
198    ($fst:ident, $st:ident $(,)?) => {
199        impls2!(@impl $fst);
200        impls2!(@impl #[doc = "Fake Variadic impl"] $fst, $st);
201    };
202    ($fst:ident $(, $i:ident)+ $(,)?) => {
203        impls2!($($i),*);
204
205        impls2!(@impl #[doc(hidden)] $fst, $($i),+);
206    };
207    (@impl $(#[$meta:meta])* $fst:ident $(, $i:ident)* $(,)?) => {
208        $(#[$meta])*
209        impl<'a, $fst, $($i),*> Unpack
210        for &'a ($fst, $($i),*)
211        {
212            type Output = (&'a $fst, $(&'a $i),*);
213
214            fn unpack(self) -> Self::Output {
215                #[allow(non_snake_case)]
216                let ($fst, $($i),*) = self;
217                ($fst, $($i),*)
218            }
219        }
220        $(#[$meta])*
221        impl<'a, $fst, $($i),*> Unpack
222        for &'a mut ($fst, $($i),*)
223        {
224            type Output = (&'a mut $fst, $(&'a mut $i),*);
225
226            fn unpack(self) -> Self::Output {
227                #[allow(non_snake_case)]
228                let ($fst, $($i),*) = self;
229                ($fst, $($i),*)
230            }
231        }
232        $(#[$meta])*
233        impl<'a, $fst: ?Sized, $($i: ?Sized),*> Unpack
234        for (&'a mut $fst, $(&'a mut $i),*)
235        {
236            type Output = (&'a $fst, $(&'a $i),*);
237
238            fn unpack(self) -> Self::Output {
239                #[allow(non_snake_case)]
240                let ($fst, $($i),*) = self;
241                ($fst, $($i),*)
242            }
243        }
244    };
245}
246impls2!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,);
247
248#[cfg(test)]
249mod tests {
250    use super::*;
251
252    #[test]
253    fn array_each_ref_test() {
254        let mut arr = [1, 2, 3];
255        let arr1 = array_each_ref(&arr);
256        assert_eq!(arr1, [&1, &2, &3]);
257        let arr2 = array_each_mut(&mut arr);
258        assert_eq!(arr2, [&mut 1, &mut 2, &mut 3]);
259        assert_eq!(arr, [1, 2, 3]);
260        *array_each_mut(&mut arr)[1] += 1;
261        assert_eq!(arr, [1, 3, 3]);
262    }
263}