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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*!
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:<br>
`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.
<br>Eg: `0`
- Ranges:
Returns a reference to an array with the elements from the start of the range,
as long as the range.
<br>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.
<br>Eg: `..2`, `..=2`, `2..`, `..`.
For an example of using every type of argument [look here](#every-arg-type-example)
# 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`.<br>
In `multindex!(slice; 0, 4..10, 20, 6)`, `LeftArgument` is `1` `RightArgument` is `3`.<br>
### `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`<br>
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`<br>
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`<br>
In `multindex!(slice; 1, 3, 5..=usize::MAX)`, `WhichArgument` is `2`.
# Examples
<span id="every-arg-type-example"></span>
### 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.
```rust
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],));
}
```
*/