1#![deny(warnings)]
29#![no_std]
30
31#[cfg(test)]
32#[macro_use]
33extern crate std;
34
35#[macro_export]
57macro_rules! array_ref {
58 ($arr:expr, $offset:expr, $len:expr) => {{
59 {
60 #[inline]
61 unsafe fn as_array<T>(slice: &[T]) -> &[T; $len] {
62 &*(slice.as_ptr() as *const [_; $len])
63 }
64 let offset = $offset;
65 let slice = & $arr[offset..offset + $len];
66 #[allow(unused_unsafe)]
67 unsafe {
68 as_array(slice)
69 }
70 }
71 }}
72}
73
74#[macro_export]
105macro_rules! array_refs {
106 ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{
107 {
108 use std::slice;
109 #[inline]
110 #[allow(unused_assignments)]
111 unsafe fn as_arrays<T>(a: &[T]) -> ( $( &[T; $pre], )* &[T], $( &[T; $post], )*) {
112 let min_len = $( $pre + )* $( $post + )* 0;
113 let var_len = a.len() - min_len;
114 assert!(a.len() >= min_len);
115 let mut p = a.as_ptr();
116 ( $( {
117 let aref = & *(p as *const [T; $pre]);
118 p = p.offset($pre as isize);
119 aref
120 } ),* , {
121 let sl = slice::from_raw_parts(p as *const T, var_len);
122 p = p.offset(var_len as isize);
123 sl
124 }, $( {
125 let aref = & *(p as *const [T; $post]);
126 p = p.offset($post as isize);
127 aref
128 } ),*)
129 }
130 let input = $arr;
131 #[allow(unused_unsafe)]
132 unsafe {
133 as_arrays(input)
134 }
135 }
136 }};
137 ( $arr:expr, $( $len:expr ),* ) => {{
138 {
139 #[inline]
140 #[allow(unused_assignments)]
141 unsafe fn as_arrays<T>(a: &[T; $( $len + )* 0 ]) -> ( $( &[T; $len], )* ) {
142 let mut p = a.as_ptr();
143 ( $( {
144 let aref = &*(p as *const [T; $len]);
145 p = p.offset($len as isize);
146 aref
147 } ),* )
148 }
149 let input = $arr;
150 #[allow(unused_unsafe)]
151 unsafe {
152 as_arrays(input)
153 }
154 }
155 }}
156}
157
158
159#[macro_export]
200macro_rules! mut_array_refs {
201 ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{
202 {
203 use std::slice;
204 #[inline]
205 #[allow(unused_assignments)]
206 unsafe fn as_arrays<T>(a: &mut [T]) -> ( $( &mut [T; $pre], )* &mut [T], $( &mut [T; $post], )*) {
207 let min_len = $( $pre + )* $( $post + )* 0;
208 let var_len = a.len() - min_len;
209 assert!(a.len() >= min_len);
210 let mut p = a.as_mut_ptr();
211 ( $( {
212 let aref = &mut *(p as *mut [T; $pre]);
213 p = p.offset($pre as isize);
214 aref
215 } ),* , {
216 let sl = slice::from_raw_parts_mut(p as *mut T, var_len);
217 p = p.offset(var_len as isize);
218 sl
219 }, $( {
220 let aref = &mut *(p as *mut [T; $post]);
221 p = p.offset($post as isize);
222 aref
223 } ),*)
224 }
225 let input = $arr;
226 #[allow(unused_unsafe)]
227 unsafe {
228 as_arrays(input)
229 }
230 }
231 }};
232 ( $arr:expr, $( $len:expr ),* ) => {{
233 {
234 #[inline]
235 #[allow(unused_assignments)]
236 unsafe fn as_arrays<T>(a: &mut [T; $( $len + )* 0 ]) -> ( $( &mut [T; $len], )* ) {
237 let mut p = a.as_mut_ptr();
238 ( $( {
239 let aref = &mut *(p as *mut [T; $len]);
240 p = p.offset($len as isize);
241 aref
242 } ),* )
243 }
244 let input = $arr;
245 #[allow(unused_unsafe)]
246 unsafe {
247 as_arrays(input)
248 }
249 }
250 }};
251}
252
253#[macro_export]
278macro_rules! array_mut_ref {
279 ($arr:expr, $offset:expr, $len:expr) => {{
280 {
281 #[inline]
282 unsafe fn as_array<T>(slice: &mut [T]) -> &mut [T; $len] {
283 &mut *(slice.as_mut_ptr() as *mut [_; $len])
284 }
285 let offset = $offset;
286 let slice = &mut $arr[offset..offset + $len];
287 #[allow(unused_unsafe)]
288 unsafe {
289 as_array(slice)
290 }
291 }
292 }}
293}
294
295
296#[cfg(test)]
297mod test {
298
299extern crate quickcheck;
300
301use std::vec::Vec;
302
303#[test]
306#[should_panic]
307fn checks_bounds() {
308 let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
309 let bar = array_ref!(foo, 1, 11);
310 println!("I am checking that I can dereference bar[0] = {}", bar[0]);
311}
312
313#[test]
314fn simple_case_works() {
315 fn check(expected: [u8; 3], actual: &[u8; 3]) {
316 for (e, a) in (&expected).iter().zip(actual.iter()) {
317 assert_eq!(e, a)
318 }
319 }
320 let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
321 {
322 let bar = array_ref!(foo, 2, 3);
323 check([2, 3, 4], bar);
324 }
325 check([0, 1, 2], array_ref!(foo, 0, 3));
326 fn zero2(x: &mut [u8; 2]) {
327 x[0] = 0;
328 x[1] = 0;
329 }
330 zero2(array_mut_ref!(foo, 8, 2));
331 check([0, 0, 10], array_ref!(foo, 8, 3));
332}
333
334
335#[test]
336fn check_array_ref_5() {
337 fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
338 if data.len() < offset + 5 {
339 return quickcheck::TestResult::discard();
340 }
341 let out = array_ref!(data, offset, 5);
342 quickcheck::TestResult::from_bool(out.len() == 5)
343 }
344 quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
345}
346
347#[test]
348fn check_array_ref_out_of_bounds_5() {
349 fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
350 if data.len() >= offset + 5 {
351 return quickcheck::TestResult::discard();
352 }
353 quickcheck::TestResult::must_fail(move || {
354 array_ref!(data, offset, 5);
355 })
356 }
357 quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
358}
359
360#[test]
361fn check_array_mut_ref_7() {
362 fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
363 if data.len() < offset + 7 {
364 return quickcheck::TestResult::discard();
365 }
366 let out = array_mut_ref!(data, offset, 7);
367 out[6] = 3;
368 quickcheck::TestResult::from_bool(out.len() == 7)
369 }
370 quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
371}
372
373
374#[test]
375fn check_array_mut_ref_out_of_bounds_32() {
376 fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
377 if data.len() >= offset + 32 {
378 return quickcheck::TestResult::discard();
379 }
380 quickcheck::TestResult::must_fail(move || {
381 array_mut_ref!(data, offset, 32);
382 })
383 }
384 quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
385}
386
387
388#[test]
389fn test_5_array_refs() {
390 let mut data: [usize; 128] = [0; 128];
391 for i in 0..128 {
392 data[i] = i;
393 }
394 let data = data;
395 let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3, 100, 10);
396 assert_eq!(a.len(), 1 as usize);
397 assert_eq!(b.len(), 14 as usize);
398 assert_eq!(c.len(), 3 as usize);
399 assert_eq!(d.len(), 100 as usize);
400 assert_eq!(e.len(), 10 as usize);
401 assert_eq!(a, array_ref![data, 0, 1]);
402 assert_eq!(b, array_ref![data, 1, 14]);
403 assert_eq!(c, array_ref![data, 15, 3]);
404 assert_eq!(e, array_ref![data, 118, 10]);
405}
406
407#[test]
408fn test_5_array_refs_dotdot() {
409 let mut data: [usize; 128] = [0; 128];
410 for i in 0..128 {
411 data[i] = i;
412 }
413 let data = data;
414 let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3; ..; 10);
415 assert_eq!(a.len(), 1 as usize);
416 assert_eq!(b.len(), 14 as usize);
417 assert_eq!(c.len(), 3 as usize);
418 assert_eq!(d.len(), 100 as usize);
419 assert_eq!(e.len(), 10 as usize);
420 assert_eq!(a, array_ref![data, 0, 1]);
421 assert_eq!(b, array_ref![data, 1, 14]);
422 assert_eq!(c, array_ref![data, 15, 3]);
423 assert_eq!(e, array_ref![data, 118, 10]);
424}
425
426
427#[test]
428fn test_5_mut_xarray_refs() {
429 let mut data: [usize; 128] = [0; 128];
430 {
431 let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3, 100, 10);
433 assert_eq!(a.len(), 1 as usize);
434 assert_eq!(b.len(), 14 as usize);
435 assert_eq!(c.len(), 3 as usize);
436 assert_eq!(d.len(), 100 as usize);
437 assert_eq!(e.len(), 10 as usize);
438 *a = [1; 1];
439 *b = [14; 14];
440 *c = [3; 3];
441 *d = [100; 100];
442 *e = [10; 10];
443 }
444 assert_eq!(&[1;1], array_ref![data, 0, 1]);
445 assert_eq!(&[14;14], array_ref![data, 1, 14]);
446 assert_eq!(&[3;3], array_ref![data, 15, 3]);
447 assert_eq!(&[10;10], array_ref![data, 118, 10]);
448}
449
450#[test]
451fn test_5_mut_xarray_refs_with_dotdot() {
452 let mut data: [usize; 128] = [0; 128];
453 {
454 let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3; ..; 10);
456 assert_eq!(a.len(), 1 as usize);
457 assert_eq!(b.len(), 14 as usize);
458 assert_eq!(c.len(), 3 as usize);
459 assert_eq!(d.len(), 100 as usize);
460 assert_eq!(e.len(), 10 as usize);
461 *a = [1; 1];
462 *b = [14; 14];
463 *c = [3; 3];
464 *e = [10; 10];
465 }
466 assert_eq!(&[1;1], array_ref![data, 0, 1]);
467 assert_eq!(&[14;14], array_ref![data, 1, 14]);
468 assert_eq!(&[3;3], array_ref![data, 15, 3]);
469 assert_eq!(&[10;10], array_ref![data, 118, 10]);
470}
471
472}