@-bindingsHere’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.
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/.