array-lit 0.2.0

Macros for array and `Vec` literals with superpowers
Documentation
# array-lit

[Documentation](https://docs.rs/array-lit/0/array_lit/index.html) · [Crates.io](https://crates.io/crates/array-lit) · [Lib.rs](https://lib.rs/crates/array-lit)


[Rust](https://www.rust-lang.org/) macros for array and `Vec` literals with superpowers.
The macro for arrays is called `arr!`; the macro for `Vec` is called `vec!`
and shadows the macro from the standard library.

They allow creating an array or `Vec` where only some elements are
specified, and the rest is set to a default value.

The following macro specifies three consecutive values at index 0:

```rust
let a = arr![0; 8; { [0]: [1, 2, 3] }];
assert_eq!(a, [1, 2, 3, 0, 0, 0, 0, 0]);
```

The square brackets are only needed when specifying multiple consecutive
elements:

```rust
let a = arr![1; 8; { 6: 0 }];
assert_eq!(a, [1, 1, 1, 1, 1, 1, 0, 1]);
```

You can specify as many single and consecutive values as you like:

```rust
let a = arr![0; 8; {
    6: 1,            // 1 at index 6
    [2]: [3, 4],     // 3 and 4 starting from index 2
    7: 5,            // 5 at index 7
}];
assert_eq!(a, [0, 0, 3, 4, 0, 0, 1, 5]);
```

The familiar array syntax (`arr![a; N]` and `arr![a, b, c]`) is also
supported, so the `vec!` macro from this crate is a drop-in replacement for
`std::vec!`.

## How does it work?

The macros generate a block that first creates a array or `Vec`, and then
inserts the specified values:

```rust
arr![4; 10; { 0: 0, 1: 1 }]
// is expanded to
{
    let mut arr = [4; 10];  // in the vec! macro, std::vec! is used
    arr[0] = 0;
    arr[1] = 1;
    arr
}
```

If an array is inserted that is not of the form `[a, b, c, ..]`, a loop is
used:

```rust
arr![4; 10; { [1]: [2; 4] }]
// is expanded to
{
    let mut arr = [4; 10];
    let mut i = 1;
    let end = i + 4;
    while i < end {
        arr[i] = 2;
        i += 1;
    }
    arr
}
```

This even works for slices, arrays and `Vec`s created at runtime:

```rust
let my_slice = &[1, 2, 3, 4];
arr![4; 10; { [1]: my_slice }];
```

## What about array lifetimes?

In trivial cases such as `arr![3; 5]`, the `'static` lifetime is inferred
for array literals. This means that they have the exact same behavior as
normal array literals.

In the other cases, the `'static` lifetime is not inferred. This means that
the array literal is computed at runtime and doesn't have a fixed memory
location. It also means that the following

```rust
// does NOT compile!
fn return_temporary() -> &'static [i32; 4] {
    &arr![0; 4; { 0: 1 }]
}
```

produces `error[E0515]: cannot return reference to temporary value`. This
can be solved by assigning the literal to a `const` or `static` variable
first:

```rust
fn return_temporary() -> &'static [i32; 4] {
    static ARR: &[i32; 4] = &arr![0; 4; { 0: 1 }];
    ARR
}
```

Values assigned to a `static` or `const` variable must be constant. Due to
limitations in the compiler, macros that expand to loops aren't allowed
there:

```rust
// does NOT compile!

const ARR: [i32; 4] = arr![0; 16; { [0]: [1; 8] }];
// this is expanded to a loop ~~~~~~~~~~~^^^^^^
```

Note that `const` enforces **const evaluation**, which means that the whole
array is included in the application binary. This might not be desirable if
the array is large.

## Usage

Import the macros with

```rust
use array_lit::{arr, vec};
```

If you don't want to shadow `std::vec!`, you can rename the macro:

```rust
use array_lit::{arr, vec as vector};
```

Importing the macros globally is also supported, although not recommended:

```rust
#[macro_use]
extern crate array_lit;
```

## Custom indices

If you want to use your own `Index`/`IndexMut` implementation in these
macros, you probably need an extra pair of parentheses:

```rust
#[derive(Copy, Clone)]
struct S(bool);

/// Your custom index
struct Idx(usize);

impl std::ops::Index<Idx> for Vec<S> {
    type Output = bool;
    // etc.
}

impl std::ops::IndexMut<Idx> for Vec<S> {
    // etc.
}

vec![S(true); 1000; { (Idx(16)): false }];
// parens needed ~~~~~^~~~~~~~^
```

## `no_std` support

This library supports `no_std`, if default features are disabled.
This makes the `vec!` macro unavailable.

## Minimum required Rust version

Requires Rust 1.33.

# License

Licensed under **MIT** or **Apache 2.0** at your choice.