Skip to content

Commit

Permalink
add experimental alternative .. syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
droundy committed Apr 25, 2017
1 parent 7b5a1b1 commit 4b71684
Showing 1 changed file with 102 additions and 1 deletion.
103 changes: 102 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(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]
Expand Down Expand Up @@ -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<T>(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]
Expand All @@ -182,7 +242,7 @@ macro_rules! mut_array_refs {
as_arrays(input)
}
}
}}
}};
}

/// You can use `array_mut_ref` to generate a mutable array reference
Expand Down Expand Up @@ -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() {
Expand All @@ -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

0 comments on commit 4b71684

Please sign in to comment.