`ary` - The array literal of the gods.
=====
Rust provides two syntaxes for array literals: `[a, b, c]`, and `[x; count]`.
When building complex `const` arrays, having only these two forms can be
quite limiting.
This library provides the `ary![]` macro to improve this situation.
# Array Splatting
First, we allow an element expression to begin with `in`, which indicates
it should be flattened into the overall array. The expression must be a
`const` array or slice. For example:
```rs
const MACRO: &[u8] = b"ary![]";
assert_eq!(&ary![0x3a, 0x3a, in MACRO, 0x3b], b"::ary![];");
assert_eq!(&ary![in b"ary![]"; 3], b"ary![]ary![]ary![]");
```
Note that because this may be *any* `const` expression, we can easily build
varying-size arrays.
```rs
const fn make_slice() -> &'static [u8] {
// ...
}
const WORDS: &[u8] = &ary![in make_slice(); 3];
assert_eq!(WORDS.len() % 3, 0);
```
# Range Modifiers
After all of the elements, *modifiers* for ranges of the constructed array
can be specified by placing range-value pairs after a `=>` token.
```rs
const ARRAY: &[i32] = &ary![0; 32 =>
14..=17: [-1; _], // Length of a Rust array literal can be inferred.
29..: [-2, -2, -2], // Unbounded ranges work too.
31: 42, // Single elements can be set directly.
(1 + 1): 2, // Complex index expressions must be wrapped in parens to
// avoid a syntax ambiguity.
];
assert_eq!(ARRAY, &[
0, 0, 2, 0, 0, -6, -7, -8, -9, -10, 1, 2, 3, 0, -1, -1,
-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, 42,
]);
// You can use .. to replace the contents of the whole array.
const RANGE: &[i32] = &ary![0; 9 => ..: |i| i as i32 + 1];
assert_eq!(RANGE, &[1, 2, 3, 4, 5, 6, 7, 8, 9]);
```
## Inferring Array Length from Ranges
It is possible to skip the element expressions and proceed to using range
modifiers; in this case, the size of the array will be inferred from the
upper bounds of the given modifiers.
```rs
const EVENS: [usize; 8] = ary![=> ..8: |i| i * 2];
assert_eq!(EVENS, [0, 2, 4, 6, 8, 10, 12, 14]);
// Unbounded ranges do not contribute to the inferred size.
const EMPTY: [i32; 0] = ary![=> ..: |_| unreachable!()];
// Lower bounds of unbounded-above ranges *do* contribute, though.
const NONEMPTY: [i32; 10] = ary![=>
..: [42; _],
10..: [-1; _],
];
```