From 4b716844824119770dc71c9afd4f48f3037143ec Mon Sep 17 00:00:00 2001 From: David Roundy Date: Mon, 24 Apr 2017 21:18:45 -0700 Subject: [PATCH] add experimental alternative .. syntax --- src/lib.rs | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e2981a3..acb3985 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,6 +102,36 @@ macro_rules! array_ref { /// ``` #[macro_export] macro_rules! array_refs { + ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{ + { + use std::slice; + #[inline] + #[allow(unused_assignments)] + unsafe fn as_arrays(a: &[T]) -> ( $( &[T; $pre], )* &[T], $( &[T; $post], )*) { + let min_len = $( $pre + )* $( $post + )* 0; + let var_len = a.len() - min_len; + assert!(a.len() >= min_len); + let mut p = a.as_ptr(); + ( $( { + let aref = & *(p as *const [T; $pre]); + p = p.offset($pre as isize); + aref + } ),* , { + let sl = slice::from_raw_parts(p as *const T, var_len); + p = p.offset(var_len as isize); + sl + }, $( { + let aref = & *(p as *const [T; $post]); + p = p.offset($post as isize); + aref + } ),*) + } + let input = $arr; + unsafe { + as_arrays(input) + } + } + }}; ( $arr:expr, $( $len:expr ),* ) => {{ { #[inline] @@ -165,6 +195,36 @@ macro_rules! array_refs { /// ``` #[macro_export] macro_rules! mut_array_refs { + ( $arr:expr, $( $pre:expr ),* ; .. ; $( $post:expr ),* ) => {{ + { + use std::slice; + #[inline] + #[allow(unused_assignments)] + unsafe fn as_arrays(a: &mut [T]) -> ( $( &mut [T; $pre], )* &mut [T], $( &mut [T; $post], )*) { + let min_len = $( $pre + )* $( $post + )* 0; + let var_len = a.len() - min_len; + assert!(a.len() >= min_len); + let mut p = a.as_mut_ptr(); + ( $( { + let aref = &mut *(p as *mut [T; $pre]); + p = p.offset($pre as isize); + aref + } ),* , { + let sl = slice::from_raw_parts_mut(p as *mut T, var_len); + p = p.offset(var_len as isize); + sl + }, $( { + let aref = &mut *(p as *mut [T; $post]); + p = p.offset($post as isize); + aref + } ),*) + } + let input = $arr; + unsafe { + as_arrays(input) + } + } + }}; ( $arr:expr, $( $len:expr ),* ) => {{ { #[inline] @@ -182,7 +242,7 @@ macro_rules! mut_array_refs { as_arrays(input) } } - }} + }}; } /// You can use `array_mut_ref` to generate a mutable array reference @@ -338,6 +398,25 @@ fn test_5_array_refs() { assert_eq!(e, array_ref![data, 118, 10]); } +#[test] +fn test_5_array_refs_dotdot() { + let mut data: [usize; 128] = [0; 128]; + for i in 0..128 { + data[i] = i; + } + let data = data; + let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3; ..; 10); + assert_eq!(a.len(), 1 as usize); + assert_eq!(b.len(), 14 as usize); + assert_eq!(c.len(), 3 as usize); + assert_eq!(d.len(), 100 as usize); + assert_eq!(e.len(), 10 as usize); + assert_eq!(a, array_ref![data, 0, 1]); + assert_eq!(b, array_ref![data, 1, 14]); + assert_eq!(c, array_ref![data, 15, 3]); + assert_eq!(e, array_ref![data, 118, 10]); +} + #[test] fn test_5_mut_xarray_refs() { @@ -362,4 +441,26 @@ fn test_5_mut_xarray_refs() { assert_eq!(&[10;10], array_ref![data, 118, 10]); } +#[test] +fn test_5_mut_xarray_refs_with_dotdot() { + let mut data: [usize; 128] = [0; 128]; + { + // temporarily borrow the data to modify it. + let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3; ..; 10); + assert_eq!(a.len(), 1 as usize); + assert_eq!(b.len(), 14 as usize); + assert_eq!(c.len(), 3 as usize); + assert_eq!(d.len(), 100 as usize); + assert_eq!(e.len(), 10 as usize); + *a = [1; 1]; + *b = [14; 14]; + *c = [3; 3]; + *e = [10; 10]; + } + assert_eq!(&[1;1], array_ref![data, 0, 1]); + assert_eq!(&[14;14], array_ref![data, 1, 14]); + assert_eq!(&[3;3], array_ref![data, 15, 3]); + assert_eq!(&[10;10], array_ref![data, 118, 10]); +} + } // mod test