Nibbles of Rust

Subslice Patterns and @-bindings

Here’s a fun thing you can do:

struct Data<'a> {
    header: [u8; 4],
    body: &'a [u8]
}

fn destructure(input: &[u8]) -> Data<'_> {
    match input {
        [0x04, 0x07, a, b, c, d, body @ ..] => Data {
            header: [*a, *b, *c, *d], body,
        },
        [a, b, _, _, _, _, ..] => panic!("invalid magic number"),
        [0x04, 0x07, ..] => panic!("insufficient packet length"),
        [_a, _b, ..] => panic!("invalid magic number, and insufficient packet length"),
        [..] => panic!("insufficient packet length"),
    }
}

The things of note here are that you can use .. to stand in for a sequence of elements inside a slice (a “subslice pattern”), and that you can write name @ <some pattern> to bind the thing which was matched by a pattern to a name.

Subslice patterns were stabilized in Rust 1.42 and, together with @-bindings (colloquially known as “at-bindings”) make match expressions very useful for parsing.

Writing Group

I was motivated to write this post by a writing group we formed in the RPLCS Discord. Other posts by our group are listed here: https://www.catmonad.xyz/writing_group/.