indices 0.2.1

Zero allocation macros for retrieving multiple mutable indices from a mutable slice
Documentation

Indices

Zero allocation macros and methods for retrieving multiple mutable indices from a mutable slice safely. e.g.

let (two, four, three) = indices!(slice, 2, 4, 3);
let [two, four, three] = indices_array(slice, [2, 4, 3])

Macros

All macros are zero allocation and allow retrieving a variable number of indices at runtime. Prefer macros when the number of indices are known at compile time.

fn main() {
    struct Person {
        first: String,
        last: String,
    }
    let mut data = [
        Person { first: "John".to_string(), last: "Doe".to_string() },
        Person { first: "Jane".to_string(), last: "Smith".to_string() },
        Person { first: "Alice".to_string(), last: "Johnson".to_string() },
        Person { first: "Bob".to_string(), last: "Brown".to_string() },
        Person { first: "Charlie".to_string(), last: "White".to_string() },
    ];
    fn modify(data_slice: &mut [Person], index: usize){
        let (four, func_provided, three) = indices!(data_slice, 4, index, 3);
        four.last = "Black".to_string();
        func_provided.first = "Jack".to_string();
        three.last = "Jones".to_string();
    }
    let slice = data.as_mut_slice();
    modify(slice, 1);
    assert_eq!(data[4].last, "Black");
    assert_eq!(data[1].first, "Jack");
    assert_eq!(data[3].last, "Jones");
}

The following macros are provided:

indices!
try_indices!
indices_ordered!
try_indices_ordered!

Methods

Methods allow for more dynamic runtime retrieval when the number of indices is unknown at compile time. e.g.

fn main() {
    struct Node {
        index: usize,
        edges: Vec<usize>,
        message: String,
    }

    let mut graph = vec![
        Node { index: 0, edges: vec![1, 2], message: String::new() },
        Node { index: 1, edges: vec![0, 2], message: String::new() },
        Node { index: 2, edges: vec![3], message: String::new() },
        Node { index: 3, edges: vec![1], message: String::new() },
    ];

    fn traverse_graph(graph: &mut [Node], current: usize, start: usize) -> bool {
        if current == start { return true; }
        let edges = graph[current].edges.clone();
        let mut edge_nodes = indices_vec(graph, &edges);
        for edge_node in edge_nodes.iter_mut() {
            edge_node.message.push_str(&format!("At Node `{}` Came from Node `{}`.", edge_node.index, current));
        }
        for edge in edges {
            if traverse_graph(graph, edge, start) {
                return true;
            }
        }
        return false;
    }
    traverse_graph(&mut *graph, 2, 0);
    let answers = [
        "At Node `0` Came from Node `1`.",
        "At Node `1` Came from Node `3`.",
        "At Node `2` Came from Node `1`.",
        "At Node `3` Came from Node `2`."
    ];
    for (index, node) in graph.iter().enumerate() {
        assert_eq!(&node.message, answers[index]);
    }
}

The following methods are provided:

indices_array
indices_vec // will allocate