1use core::{
2 ops::Deref,
3 pin::Pin,
4};
5
6pub trait ThisRef<'a>: 'a {
8 type Out: ?Sized;
9
10 fn this_ref(self) -> &'a Self::Out;
12}
13
14pub trait ThisMut<'a>: ThisRef<'a> {
16 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
84pub trait Unpack: Sized {
93 type Output;
94
95 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}