1use crate::Array;
4use core::{
5 borrow::{Borrow, BorrowMut},
6 fmt::Debug,
7 ops::{Index, IndexMut, Range},
8};
9use typenum::Unsigned;
10
11#[diagnostic::on_unimplemented(note = "size may not be supported (see RustCrypto/hybrid-array#66)")]
22pub unsafe trait ArraySize: Unsigned + Debug {
23 type ArrayType<T>: AssocArraySize<Size = Self>
28 + AsRef<[T]>
29 + AsMut<[T]>
30 + Borrow<[T]>
31 + BorrowMut<[T]>
32 + From<Array<T, Self>>
33 + Index<usize>
34 + Index<Range<usize>>
35 + IndexMut<usize>
36 + IndexMut<Range<usize>>
37 + Into<Array<T, Self>>
38 + IntoIterator<Item = T>;
39}
40
41pub trait AssocArraySize: Sized {
60 type Size: ArraySize;
62}
63
64impl<T, U> AssocArraySize for Array<T, U>
65where
66 U: ArraySize,
67{
68 type Size = U;
69}
70
71pub trait AsArrayRef<T>: AssocArraySize {
99 fn as_array_ref(&self) -> &Array<T, Self::Size>;
101}
102
103pub trait AsArrayMut<T>: AsArrayRef<T> {
108 fn as_array_mut(&mut self) -> &mut Array<T, Self::Size>;
110}
111
112impl<T, U> AsArrayRef<T> for Array<T, U>
113where
114 U: ArraySize,
115{
116 fn as_array_ref(&self) -> &Self {
117 self
118 }
119}
120
121impl<T, U> AsArrayMut<T> for Array<T, U>
122where
123 U: ArraySize,
124{
125 fn as_array_mut(&mut self) -> &mut Self {
126 self
127 }
128}
129
130impl<T, U, const N: usize> AsArrayRef<T> for [T; N]
131where
132 Self: AssocArraySize<Size = U>,
133 U: ArraySize<ArrayType<T> = Self>,
134{
135 fn as_array_ref(&self) -> &Array<T, U> {
136 self.into()
137 }
138}
139
140impl<T, U, const N: usize> AsArrayMut<T> for [T; N]
141where
142 Self: AssocArraySize<Size = U>,
143 U: ArraySize<ArrayType<T> = Self>,
144{
145 fn as_array_mut(&mut self) -> &mut Array<T, U> {
146 self.into()
147 }
148}
149
150pub trait SliceExt<T>: sealed::Sealed {
152 fn as_hybrid_array<U: ArraySize>(&self) -> Option<&Array<T, U>>;
156
157 fn as_mut_hybrid_array<U: ArraySize>(&mut self) -> Option<&mut Array<T, U>>;
162
163 fn as_hybrid_chunks<U: ArraySize>(&self) -> (&[Array<T, U>], &[T]);
169
170 fn as_hybrid_chunks_mut<U: ArraySize>(&mut self) -> (&mut [Array<T, U>], &mut [T]);
176}
177
178impl<T> SliceExt<T> for [T] {
179 fn as_hybrid_array<U: ArraySize>(&self) -> Option<&Array<T, U>> {
180 Array::slice_as_array(self)
181 }
182
183 fn as_mut_hybrid_array<U: ArraySize>(&mut self) -> Option<&mut Array<T, U>> {
184 Array::slice_as_mut_array(self)
185 }
186
187 fn as_hybrid_chunks<U: ArraySize>(&self) -> (&[Array<T, U>], &[T]) {
188 Array::slice_as_chunks(self)
189 }
190
191 fn as_hybrid_chunks_mut<U: ArraySize>(&mut self) -> (&mut [Array<T, U>], &mut [T]) {
192 Array::slice_as_chunks_mut(self)
193 }
194}
195
196impl<T> sealed::Sealed for [T] {}
197
198mod sealed {
199 pub trait Sealed {}
200}
201
202#[cfg(test)]
203mod tests {
204 use super::{AsArrayMut, AsArrayRef, SliceExt};
205 use crate::{
206 Array,
207 sizes::{U2, U3},
208 };
209
210 type A = Array<u8, U2>;
211
212 #[test]
213 fn core_as_array_ref() {
214 assert_eq!([1, 2, 3].as_array_ref(), &Array([1, 2, 3]));
215 }
216
217 #[test]
218 fn core_as_array_mut() {
219 assert_eq!([1, 2, 3].as_array_mut(), &Array([1, 2, 3]));
220 }
221
222 #[test]
223 fn hybrid_as_array_ref() {
224 assert_eq!(A::from([1, 2]).as_array_ref(), &Array([1, 2]));
225 }
226
227 #[test]
228 fn hybrid_as_array_mut() {
229 assert_eq!(A::from([1, 2]).as_array_mut(), &Array([1, 2]));
230 }
231
232 #[test]
233 fn slice_as_hybrid_array() {
234 assert_eq!([1, 2].as_hybrid_array::<U3>(), None);
235 assert_eq!([1, 2, 3].as_hybrid_array::<U3>(), Some(&Array([1, 2, 3])));
236 assert_eq!([1, 2, 3, 4].as_hybrid_array::<U3>(), None);
237 }
238
239 #[test]
240 fn slice_as_mut_hybrid_array() {
241 assert_eq!([1, 2].as_mut_hybrid_array::<U3>(), None);
242 assert_eq!(
243 [1, 2, 3].as_mut_hybrid_array::<U3>(),
244 Some(&mut Array([1, 2, 3]))
245 );
246 assert_eq!([1, 2, 3, 4].as_mut_hybrid_array::<U3>(), None);
247 }
248
249 #[test]
250 fn slice_as_hybrid_chunks() {
251 let (slice_empty, rem_empty): (&[A], &[u8]) = [].as_hybrid_chunks::<U2>();
252 assert!(slice_empty.is_empty());
253 assert!(rem_empty.is_empty());
254
255 let (slice_one, rem_one) = [1].as_hybrid_chunks::<U2>();
256 assert!(slice_one.is_empty());
257 assert_eq!(rem_one, &[1]);
258
259 let (slice_aligned, rem_aligned) = [1u8, 2].as_hybrid_chunks::<U2>();
260 assert_eq!(slice_aligned, &[Array([1u8, 2])]);
261 assert_eq!(rem_aligned, &[]);
262
263 let (slice_unaligned, rem_unaligned) = [1u8, 2, 3].as_hybrid_chunks::<U2>();
264 assert_eq!(slice_unaligned, &[Array([1u8, 2])]);
265 assert_eq!(rem_unaligned, &[3]);
266 }
267
268 #[test]
269 fn slice_as_hybrid_chunks_mut() {
270 let (slice_empty, rem_empty): (&mut [A], &mut [u8]) = [].as_hybrid_chunks_mut::<U2>();
271 assert!(slice_empty.is_empty());
272 assert!(rem_empty.is_empty());
273
274 let mut arr1 = [1];
275 let (slice_one, rem_one) = arr1.as_hybrid_chunks_mut::<U2>();
276 assert!(slice_one.is_empty());
277 assert_eq!(rem_one, &[1]);
278
279 let mut arr2 = [1u8, 2];
280 let (slice_aligned, rem_aligned) = arr2.as_hybrid_chunks_mut::<U2>();
281 assert_eq!(slice_aligned, &mut [Array([1u8, 2])]);
282 assert_eq!(rem_aligned, &mut []);
283
284 let mut arr3 = [1u8, 2, 3];
285 let (slice_unaligned, rem_unaligned) = arr3.as_hybrid_chunks_mut::<U2>();
286 assert_eq!(slice_unaligned, &mut [Array([1u8, 2])]);
287 assert_eq!(rem_unaligned, &mut [3]);
288 }
289}