chunks_exact(N) Item is &'a [T] and not &'a [T: N]

ChunksExact: ChunksExact in std::slice - Rust

Some example (sound to my eye) code motivating this discussion: Rust Playground

Calling .chunks_exact(N) on an iterable results in chunks that are exactly N items long, but the resulting Item type is &'a [T] and not &'a [T: N].

As a result, sound code expecting known-length slices won't work. If it did, you would be able to convert Vec<u8> to Vec<u16> (or others) using entirely safe methods. This could be really useful for converting a big buffer where the specific layout might not be known at compile time, as in many network protocols.

I haven't contributed to the compiler, but I think that this is possible using specialization. Even if it were only implemented for [u8] up to N=16, I think that would be useful because that would allow you to convert [u8] slices to [u128] slices using only safe code, but perhaps covering all generic cases for arbitrary N is worth the effort.

Thoughts?

Doing some more searching, I think this is actually a case where const generic would be used?

Still not sure how to implement it.

From the docs for chunks_exact:

If your chunk_size is a constant, consider using as_chunks instead, which will give references to arrays of exactly that length, rather than slices.

(Admittedly that mention was only added a few weeks ago, so you can't be blamed for not having seen it already.)

3 Likes

Wow, yeah. I think that's exactly what I had in mind.

Where is that quote exactly? I'm not seeing it.

It’s only on nightly right now, not yet on stable. Also, the target of the as_chunks link seems to be wrong. slice - Rust

So the doc change is on nightly, but the actual method I want is already on stable: slice - Rust

Cool.

1 Like

For anyone coming here from a search, here's a version of the playground code that uses this method which actually compile: Rust Playground

MAGIC

For extra fun, instead of

    let (chunks, rest) = slice.as_chunks::<4>();
    
    if rest.len() > 0 {
        return Err(());
    }

try doing

    let (chunks, []) = slice.as_chunks::<4>() else { return Err(()) };

Yeah, I noticed that too: Incorrect cross-link in `chunks_exact` docs · Issue #144555 · rust-lang/rust · GitHub

8 Likes