Dear Rustaceans,
I'm trying to split()
a slice and then collect()
them to make them back.
Here's the minimal code snippet to reproduce.
let test = b"this is very very useless string";
let x = test.split(|byte| byte.is_ascii_whitespace()).flatten().collect::<Vec<_>>();
let y = x.to_slice();
However, the type of x
is Vec<&u8>
so y
's becomes &[&u8]
,
so I cannot use other existing APIs that only takes &[u8]
.
So some questions around here.
- Is there a way to create
&[u8]
? It's primitive type so copying it wouldn't cost much. And even the assignment between u8
copies variable, and not move.
- Is there a way to convert
&[&u8]
to &[u8]
? It's challenging issue to me.
let x: Vec<u8> = test
.split(|byte| byte.is_ascii_whitespace())
.flatten()
.map(|byte| *byte) // <<<<<<<<<<
.collect::<Vec<_>>();
1 Like
AKA .copied()
.
Alternatively,
let mut x: Vec<u8> = vec![];
test.split(|byte| byte.is_ascii_whitespace()).for_each(|slice| {
x.extend_from_slice(slice)
});
let y = x.as_slice();
Note that both of these suggestions collect a Vec<u8>
and then create a local borrow to create the &[u8]
. It can't last longer than the underlying Vec
(x
). The lifetime is limited to the local function or functions you call. Just using the Vec<u8>
may suit your use case better.
(In contrast, a b"..."
is a &'static [u8; _]
(which can be coerced into a &'static [u8]
). You can copy it around everywhere .)
There's no way to directly convert a &[&u8]
to a &[u8]
as the contents of a slice are contiguous in memory. So the &[u8]
are a bunch of bytes in a row, but the &[&u8]
could be pointing to a bunch of bytes all over the place. You have to copy them out and place them somewhere else contiguously -- e.g. into a Vec<u8>
.
4 Likes