1#![no_std]
45
46#[macro_export]
50macro_rules! const_assert {
51 ($($list:ident : $ty:ty),* => $expr:expr) => {{
52 struct Assert<$(const $list: usize,)*>;
53 impl<$(const $list: $ty,)*> Assert<$($list,)*> {
54 const OK: u8 = 0 - !($expr) as u8;
55 }
56 Assert::<$($list,)*>::OK
57 }};
58 ($expr:expr) => {
59 const OK: u8 = 0 - !($expr) as u8;
60 };
61}
62
63pub unsafe trait SubArray {
73 type Item;
77
78 fn sub_array_ref<const OFFSET: usize, const M: usize>(&self) -> &[Self::Item; M];
97
98 fn sub_array_mut<const OFFSET: usize, const M: usize>(&mut self) -> &mut [Self::Item; M];
111}
112
113unsafe impl<T, const N: usize> SubArray for [T; N] {
115 type Item = T;
116
117 #[allow(unsafe_code)]
118 fn sub_array_ref<const OFFSET: usize, const M: usize>(&self) -> &[Self::Item; M] {
119 const_assert!(OFFSET: usize, M: usize, N: usize => OFFSET + M <= N);
120 unsafe { &*(self.as_ptr().add(OFFSET) as *const [T; M]) }
121 }
122
123 #[allow(unsafe_code)]
124 fn sub_array_mut<const OFFSET: usize, const M: usize>(&mut self) -> &mut [Self::Item; M] {
125 const_assert!(OFFSET: usize, M: usize, N: usize => OFFSET + M <= N);
126 unsafe { &mut *(self.as_ptr().add(OFFSET) as *mut [T; M]) }
127 }
128}
129
130unsafe impl<T> SubArray for &mut T
132where
133 T: SubArray,
134{
135 type Item = T::Item;
136
137 fn sub_array_ref<const OFFSET: usize, const N: usize>(&self) -> &[Self::Item; N] {
138 (**self).sub_array_ref::<OFFSET, N>()
139 }
140
141 fn sub_array_mut<const OFFSET: usize, const N: usize>(&mut self) -> &mut [Self::Item; N] {
142 (**self).sub_array_mut::<OFFSET, N>()
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 extern crate alloc;
149
150 use alloc::string::String;
151 use alloc::string::ToString;
152
153 use super::*;
154
155 #[test]
156 fn empty_ref() {
157 let arr = [0_u8; 0];
158 assert_eq!(arr.sub_array_ref::<0, 0>(), &[]);
159 }
160
161 #[test]
162 fn empty_mut() {
163 let mut arr = [0_u8; 0];
164 assert_eq!(arr.sub_array_mut::<0, 0>(), &mut []);
165 }
166
167 #[test]
168 fn full_ref() {
169 let arr = [1, 2, 3_i8];
170 assert_eq!(arr.sub_array_ref::<0, 3>(), &[1, 2, 3]);
171 }
172
173 #[test]
174 fn full_mut() {
175 let mut arr = [1, 2, 3_i8];
176 assert_eq!(arr.sub_array_mut::<0, 3>(), &mut [1, 2, 3]);
177 }
178
179 #[test]
180 fn first_ref() {
181 let arr = [1, 2, 3_u16];
182 assert_eq!(arr.sub_array_ref::<0, 1>(), &[1]);
183 }
184
185 #[test]
186 fn first_mut() {
187 let mut arr = [1, 2, 3_u16];
188 assert_eq!(arr.sub_array_mut::<0, 1>(), &mut [1]);
189 }
190
191 #[test]
192 fn middle_ref() {
193 let arr = [1, 2, 3_i16];
194 assert_eq!(arr.sub_array_ref::<1, 1>(), &[2]);
195 }
196
197 #[test]
198 fn middle_mut() {
199 let mut arr = [1, 2, 3_i16];
200 assert_eq!(arr.sub_array_mut::<1, 1>(), &mut [2]);
201 }
202
203 #[test]
204 fn last_ref() {
205 let arr = [1, 2, 3_i16];
206 assert_eq!(arr.sub_array_ref::<2, 1>(), &[3]);
207 }
208
209 #[test]
210 fn last_mut() {
211 let mut arr = [1, 2, 3_i16];
212 assert_eq!(arr.sub_array_mut::<2, 1>(), &mut [3]);
213 }
214
215 #[derive(Debug, PartialEq, Eq)]
216 struct NotClone(&'static str);
217
218 const NOT_CLONE_ARRAY: [NotClone; 5] = [
219 NotClone("abc"),
220 NotClone("foo"),
221 NotClone("bar"),
222 NotClone("qux"),
223 NotClone("fox"),
224 ];
225
226 #[test]
227 fn not_clone_ref() {
228 let exp_arr = [NotClone("foo"), NotClone("bar"), NotClone("qux")];
229 let arr = NOT_CLONE_ARRAY;
230 assert_eq!(arr.sub_array_ref::<1, 3>(), &exp_arr);
231 }
232
233 #[test]
234 fn not_clone_mut() {
235 let mut exp_arr = [NotClone("foo"), NotClone("bar"), NotClone("qux")];
236 let mut arr = NOT_CLONE_ARRAY;
237 assert_eq!(arr.sub_array_mut::<1, 3>(), &mut exp_arr);
238 }
239
240 #[test]
241 fn some_strings() {
242 let arr: [String; 5] = NOT_CLONE_ARRAY.map(|s| s.0.to_string());
243 assert_eq!(
244 arr.sub_array_ref::<2, 2>(),
245 &[String::from("bar"), String::from("qux")]
246 );
247 }
248}