[−][src]Module multindex::indexing_macro_docs
Documents what the indexing macros share in common.
Limitations
The macros from this crate only accept compile-time indices/ranges not derived from generic parameters.
The non-generic limitation might be lifted in newer versions, when const generics and compile-time function evaluation support improves.
Parameters
The macros take arguments of this form:
macro_name!(slice; indexing_argument0, indexing_argument1, indexing_argument2, etcetera )
.
Indexing arguments can be any of:
-
Integers: An individual index, returning a reference to the element at that index.
Eg:0
-
Ranges: Returns a reference to an array with the elements from the start of the range, as long as the range.
Eg:1..2
,3..=4
. -
Unbounded ranges: Returns a slice if the range is unbounded at the end of the argument list. Otherwise returns an reference to an array.
Eg:..2
,..=2
,2..
,..
.
For an example of using every type of argument look here
Errors
Compile-time errors
The macros report errors at compile-time using type errors with types of this form:
NameOfTheError__MeaningOfTheTypeParameter<[(); Integer ]>
.
NameOfTheError
is the kind of error that happened.
MeaningOfTheTypeParameter
is what the Integer
in the type parameter means,
usually which parameter(s) triggered that error.
Runtime errors
The macros don't catch all errors at compile-time.
They always check at runtime that the arguments are in bounds of the array or slice, with one check.
Once const-generics are stable (and powerful enough to express it generically), a new release could be made with macros that check that the arguments are in bounds of arrays, at compile-time.
The error types
These are the errors that this macro encodes as types
OverlappingIndexArguments__ArgumentsAre<[(); LeftArgument ], [(); RightArgument ]>
:
When an argument overlaps with another one,
if this was allowed to compile it would allow aliasing &mut
references.
LeftArgument
is which argument overlaps with another one, starting at 0.
RightArgument
is which argument overlaps with LeftArgument
, starting at 0.
Examples:
In multindex!(slice; 10, 20, 10)
, LeftArgument
is 0
RightArgument
is 2
.
In multindex!(slice; 0, 4..10, 20, 6)
, LeftArgument
is 1
RightArgument
is 3
.
NextStartIsUnbounded__CurrentArgumentIs<[(); WhichArgument ]>
:
When a range argument with an unbounded end is followed by a range argument with an unbounded start.
WhichArgument
is which argument triggers the error, starting at 0.
Examples:
In multindex!(slice; 3.., ..5)
, WhichArgument
is 0
In multindex!(slice; 1, 3, 5.., ..)
, WhichArgument
is 2
.
NextStartIsLessThanCurrent__CurrentArgumentIs<[(); WhichArgument ]>
:
When a range argument with an unbounded end is followed by an argument that compares less to it.
WhichArgument
is which argument triggers the error, starting at 0.
Examples:
In multindex!(slice; 13.., 4)
, WhichArgument
is 0
In multindex!(slice; 1, 3, 10.., 8)
, WhichArgument
is 2
.
InclusiveUptoUsizeMax__CurrentArgumentis<[(); WhichArgument ]>
:
When an inclusive range argument ends at usize::MAX
.
This is an error to simplify the implementation of this crate.
WhichArgument
is which argument triggers the error, starting at 0.
Examples:
In multindex!(slice; ..=usize::MAX)
, WhichArgument
is 0
In multindex!(slice; 1, 3, 5..=usize::MAX)
, WhichArgument
is 2
.
Examples
Every argument type
This example demonstrates every type of argument being used.
The type annotations in this example are for the reader, all the types can be inferred.
use multindex::multindex_mut; { // Index: 0 1 2 3 4 5 6 7 8 let mut arr = [3, 5, 8, 13, 21, 34, 55, 89, 144]; // Single argument invocations of the macro return a single element tuple. assert_eq!(multindex_mut!(arr; 0), (&mut 3,)); assert_eq!(multindex_mut!(arr; 0, 2, 4 ), (&mut 3, &mut 8, &mut 21)); } { // Index: 0 1 2 3 4 5 6 7 8 let mut arr = [3, 5, 8, 13, 21, 34, 55, 89, 144]; // Trailing `n..` ranges return slice references with the rest of the slice let trailing: (&mut [i32],) = multindex_mut!(arr; 6..); assert_eq!(trailing, (&mut [55, 89, 144][..],)); // Initial/middle `n..` ranges return references to arrays let middle: (&mut [i32; 2], &mut i32) = multindex_mut!(arr; 1.., 3); assert_eq!(middle, (&mut [5, 8], &mut 13)); } { // Index: 0 1 2 3 4 5 6 7 8 let mut arr = [3, 5, 8, 13, 21, 34, 55, 89, 144]; // Trailing `..` ranges return slice references with the rest of the slice let trailing: (&mut i32, &mut [i32],) = multindex_mut!(arr; 5, ..); assert_eq!(trailing, (&mut 34, &mut [55, 89, 144][..])); // Initial/middle `..` ranges return references to arrays. let middle: (&mut i32, &mut [i32; 3], &mut i32) = multindex_mut!(arr; 0, .., 4); assert_eq!(middle, (&mut 3, &mut [5, 8, 13], &mut 21)); } { // Index: 0 1 2 3 4 5 6 7 8 let mut arr = [3, 5, 8, 13, 21, 34, 55, 89, 144]; // `n..m` / `n..=m` ranges return references to arrays let exclusive: (&mut [i32; 2],) = multindex_mut!(arr; 2..4); assert_eq!(exclusive, (&mut [8, 13],)); let inclusive: (&mut [i32; 3],) = multindex_mut!(arr; 2..=4); assert_eq!(inclusive, (&mut [8, 13, 21],)); } { // Index: 0 1 2 3 4 5 6 7 8 let mut arr = [3, 5, 8, 13, 21, 34, 55, 89, 144]; // `..n`/`..=n` ranges return references to arrays. let exclusive: (&mut i32, &mut [i32; 2]) = multindex_mut!(arr; 1, ..4); assert_eq!(exclusive, (&mut 5, &mut [8, 13])); let inclusive: (&mut [i32; 5],) = multindex_mut!(arr; ..=4); assert_eq!(inclusive, (&mut [3, 5, 8, 13, 21],)); }