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);