#how do I go from `Box<[u8]>` to `Box<str>`?
18 messages · Page 1 of 1 (latest)
.into_vec() -> String::from_utf8 -> into_boxed_str()
Shouldn't reallocate
?eval ```rs
let x: Box<[u8]> = Box::new(*b"hello, world!");
let y: Vec<u8> = x.into_vec();
let z: String = String::from_utf8(y).unwrap();
let w: Box<str> = z.into_boxed_str();
w
"hello, world!"```
Yeah,ideally there'd be a TryFrom<Box<[u8]>> for Box<str>
Don't do this (see T-Dark, World's comment below).
?play ```rust
fn from_boxed_utf8(bytes: Box<[u8]>) -> Result<Box<str>, (Box<[u8]>, core::str::Utf8Error)> {
match core::str::from_utf8(&bytes) {
Ok(_) => Ok(unsafe { core::mem::transmute::<Box<[u8]>, Box<str>>(bytes) }),
Err(err) => Err((bytes, err)),
}
}
You can avoid the allocation of the Vec by checking whether the bytes are valid UTF-8, and, if so, just changing the type.
If you want to do it without checking for valid UTF-8, there's std::str::from_boxed_utf8_unchecked: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html.
This code is unsound.
Box doesn't promise to have the same layout across types. You're supposed to into_raw, cast, and from_raw
fn from_boxed_utf8(bytes: Box<[u8]>) -> Result<Box<str>, (Box<[u8]>, core::str::Utf8Error)> {
match core::str::from_utf8(&bytes) {
- Ok(_) => Ok(unsafe { core::mem::transmute::<Box<[u8]>, Box<str>>(bytes) }),
+ Ok(_) => Ok(unsafe { std::str::from_boxed_utf8_unchecked(bytes) }),
Err(err) => Err((bytes, err)),
}
}
Converting a Box<[u8]> to a Vec<u8> doesn't actually allocate
The opposite direction, however, can. Though not in this case: It doesn't reallocate if len == capacity
Oh, OK. That makes sense.