arraylib/transform/as_ref.rs
1use crate::{iter::IteratorExt, Array};
2
3/// Trait for conversation between `&[T; N]` and `[&T; N]` (or `&mut [T; N]` and
4/// `[&mut T; N]`)
5pub trait ArrayAsRef<'a>: Array
6where
7 <Self as Array>::Item: 'a,
8{
9 /// Result of the 'shared' conversation, in other words `[&T; N]`
10 /// (where `T = Self::Item, N = Self::Size`)
11 type AsRef: Array<Item = &'a <Self as Array>::Item>;
12
13 /// Result of the 'unique' conversation, in other words `[&mut T; N]`
14 /// (where `T = Self::Item, N = Self::Size`)
15 type AsMut: Array<Item = &'a mut <Self as Array>::Item>;
16
17 /// Convert `&self` to `[&T; N]` (where `T = Self::Item, N = Self::Size`)
18 ///
19 /// ## Examples
20 /// ```
21 /// use arraylib::ArrayAsRef;
22 ///
23 /// let arr = [0, 1, 2, 3];
24 /// let ref_arr = arr.as_ref_array();
25 /// assert_eq!(ref_arr, [&0, &1, &2, &3]);
26 /// assert_eq!(arr, [0, 1, 2, 3]);
27 /// ```
28 /// ```
29 /// use arraylib::{ArrayAsRef, ArrayExt};
30 ///
31 /// // Don't do like this, it's just an example
32 /// fn index_of<A>(a: &A, x: A::Item) -> Option<usize>
33 /// where
34 /// for<'a> A: ArrayAsRef<'a>,
35 /// A::Item: PartialEq,
36 /// {
37 /// a.as_ref_array()
38 /// .iter_move()
39 /// .enumerate()
40 /// .find(|&(_, it)| it == &x)
41 /// .map(|(idx, _)| idx)
42 /// }
43 ///
44 /// let arr = [-2, 1, -1, 2];
45 /// assert_eq!(index_of(&arr, 1), Some(1));
46 /// assert_eq!(index_of(&arr, 2), Some(3));
47 /// assert_eq!(index_of(&arr, 0), None);
48 /// ```
49 ///
50 /// **NOTE**: it's nighly recommended to use iterators when you need to
51 /// perform more that one operation (e.g. map + as_ref) because iterators
52 /// are lazy and `ArrayAsRef` isn't.
53 ///
54 /// See also: [`as_mut_array`](crate::ArrayAsRef::as_mut_array)
55 fn as_ref_array(&'a self) -> Self::AsRef;
56
57 /// Convert `&mut self` to `[&mut T; N]` (where `T = Self::Item, N =
58 /// Self::Size`)
59 ///
60 /// ## Examples
61 /// ```
62 /// use arraylib::ArrayAsRef;
63 ///
64 /// let mut arr = [0, 1, 2, 3];
65 /// let ref_arr = arr.as_mut_array();
66 /// assert_eq!(ref_arr, [&mut 0, &mut 1, &mut 2, &mut 3]);
67 /// assert_eq!(arr, [0, 1, 2, 3]);
68 /// ```
69 /// ```
70 /// use arraylib::{ArrayAsRef, ArrayExt};
71 ///
72 /// // Don't do like this, it's just an example
73 /// fn find_and_replace<A>(a: &mut A, find: &A::Item, replace: A::Item) -> A::Item
74 /// where
75 /// for<'a> A: ArrayAsRef<'a>,
76 /// A::Item: PartialEq,
77 /// {
78 /// let mut x = a.as_mut_array().iter_move().find(|it| it == &find);
79 /// match x {
80 /// Some(ref mut inner) => core::mem::replace(inner, replace),
81 /// None => replace,
82 /// }
83 /// }
84 ///
85 /// let mut arr = [-2, 1, -1, 2];
86 /// assert_eq!(find_and_replace(&mut arr, &1, 8), 1);
87 /// assert_eq!(arr, [-2, 8, -1, 2]);
88 /// ```
89 ///
90 /// **NOTE**: it's nighly recommended to use iterators when you need to
91 /// perform more that one operation (e.g. map + as_ref) because iterators
92 /// are lazy and `ArrayAsRef` isn't.
93 ///
94 /// See also: [`as_ref_array`](crate::ArrayAsRef::as_ref_array)
95 fn as_mut_array(&'a mut self) -> Self::AsMut;
96}
97
98impl<'a, T: 'a> ArrayAsRef<'a> for [T; 0] {
99 type AsMut = [&'a mut T; 0];
100 type AsRef = [&'a T; 0];
101
102 #[inline]
103 fn as_ref_array(&'a self) -> Self::AsRef {
104 []
105 }
106
107 #[inline]
108 fn as_mut_array(&'a mut self) -> Self::AsMut {
109 []
110 }
111}
112
113macro_rules! as_ref_impl {
114 ($e:tt) => {
115 impl<'a, T: 'a> ArrayAsRef<'a> for [T; $e] {
116 type AsMut = [&'a mut T; $e];
117 type AsRef = [&'a T; $e];
118
119 #[inline]
120 fn as_ref_array(&'a self) -> Self::AsRef {
121 self.as_slice().iter().collect_array::<Self::AsRef>()
122 }
123
124 #[inline]
125 fn as_mut_array(&'a mut self) -> Self::AsMut {
126 self.as_mut_slice()
127 .iter_mut()
128 .collect_array::<Self::AsMut>()
129 }
130 }
131 };
132}
133
134array_impls!(as_ref_impl);