1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![no_std]


#[doc(hidden)]
pub use core::mem::transmute;

/**
 * Slices (via the Index trait & operation) into fixed size arrays
 *
 * Will panic with the same rules as normal slicing.
 *
 * Will not compile if bounds are not static.
 *
 * Will not compile if end bound proceeds start bound.
 *
 * # Format
 *
 * ```notest
 * index_fixed! ( {&,&mut} <slice> ; .. <end>)
 * index_fixed! ( {&,&mut} <slice> ; <start> , .. <end>)
 * index_fixed! ( {&,&mut} <slice> ; <start> , ... <end>)
 * ```
 *
 * # Examples
 *
 * ```
 * #[macro_use]
 * extern crate index_fixed;
 *
 * fn main() {
 *   let my_slice = [1, 2, 3, 4];
 *   let slice_of_2 = index_fixed!(&my_slice ; .. 2);
 *   assert_eq!(slice_of_2, &my_slice[..2]);
 * }
 * ```
 */
// FIXME example test disabled because index_fixed!() is not defined
#[macro_export]
macro_rules! index_fixed {
    (&mut $s:expr ;  .. $e:expr) => {
        index_fixed!(&mut $s; 0 , .. $e )
    };
    (&mut $s:expr ; $b:expr , ... $e:expr) => {
        index_fixed!(&mut $s; $b , .. ($e + 1))
    };
    (&mut $s:expr ; $b:expr , .. $e:expr) => { {
        fn conv<T>(b: &mut[T]) -> &mut[T;$e - $b] {
            unsafe { $crate::transmute::<*mut T, &mut[T;$e - $b]>(b.as_mut_ptr()) }
        }
        conv(&mut $s[$b..$e])
    } };
    (& $s:expr ; .. $e:expr) => {
        index_fixed!(& $s ; 0 , .. $e)
    };
    (& $s:expr ; $b:expr , ... $e:expr) => {
        index_fixed!(& $s ; $b , .. ($e + 1))
    };
    (& $s:expr ; $b:expr , .. $e:expr) => { {
        fn conv<T>(b: &[T]) -> &[T;$e - $b] {
            unsafe { $crate::transmute::<*const T, &[T;$e - $b]>(b.as_ptr()) }
        }
        conv(& $s[$b..$e])
    } };
}

/**
 * `slice::get` and `slice::get_mut`, but return an `Option<&[T;N]>` or `Option<&mut [T;N]>`
 *
 * Will not compile if bounds are not static.
 *
 * Will not compile if end bound proceeds start bound.
 *
 * # Format
 *
 * ```notest
 * index_fixed_get! ( {&,&mut} <slice> ; .. <end>)
 * index_fixed_get! ( {&,&mut} <slice> ; <start> , .. <end>)
 * index_fixed_get! ( {&,&mut} <slice> ; <start> , ... <end>)
 * ```
 *
 * # Examples
 *
 * ```
 * #[macro_use]
 * extern crate index_fixed;
 *
 * fn main() {
 *   let my_slice = [1, 2, 3, 4];
 *   let slice_of_2 = index_fixed_get!(&my_slice ; .. 2);
 *   assert_eq!(slice_of_2, Some(&[1,2]));
 * }
 * ```
 */
#[macro_export]
macro_rules! index_fixed_get {
    (&mut $s:expr ;  .. $e:expr) => {
        index_fixed_get!(&mut $s; 0 , .. $e )
    };
    (&mut $s:expr ; $b:expr , ... $e:expr) => {
        index_fixed_get!(&mut $s; $b , .. ($e + 1))
    };
    (&mut $s:expr ; $b:expr , .. $e:expr) => { {
        fn conv<T>(a: Option<&mut[T]>) -> Option<&mut[T;$e - $b]> {
            a.map(|b|
                unsafe { $crate::transmute::<*mut T, &mut [T;$e - $b]>(b.as_mut_ptr()) }
            )
        }
        conv($s.get_mut($b..$e))
    } };
    (& $s:expr ; .. $e:expr) => {
        index_fixed_get!(& $s ; 0 , .. $e)
    };
    (& $s:expr ; $b:expr , ... $e:expr) => {
        index_fixed_get!(& $s ; $b , .. ($e + 1))
    };
    (& $s:expr ; $b:expr , .. $e:expr) => { {
        fn conv<T>(a: Option<&[T]>) -> Option<&[T;$e - $b]> {
            a.map(|b|
                unsafe { $crate::transmute::<*const T, &[T;$e - $b]>(b.as_ptr()) }
            )
        }
        conv($s.get($b..$e))
    } };
}