I have a Cow with lifetime 'a and would like to turn it into a str with lifetime 'a. I "think" this should be possible, but I can't seem to make it work.
Any tips?
use std::borrow::Cow;
pub struct Test<'a> {
cow: Cow<'a, [u8]>,
slice: &'a [u8],
}
impl<'a> Test<'a> {
// doesn't work! :(
fn cow_as_str(&self) -> &'a str {
unsafe { std::str::from_utf8_unchecked(self.cow.as_ref()) }
}
// works! :)
fn slice_as_str(&self) -> &'a str {
unsafe { std::str::from_utf8_unchecked(&self.slice) }
}
}
(Playground )
You can't do that. What if your Cow
is in the Owned
state? Then there is no reference that lives for 'a
The best you can do is
impl<'a> Test<'a> {
// doesn't work! :(
fn cow_as_str(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(self.cow.as_ref()) }
}
}
Or you can check if you are in the borrowed state and then use that slice to construct the string slice
Thanks, I think you got me on the right track.
I tried to simplify in my original question... but the larger goal was to map an iterator yielding Cow<'a, [u8]>;
into an iterator yielding some form of string. Your reminder that switching on the Cow enum was probably necessary got me to the following. Seems to do what I want.
struct ByteIter<'a> {
chunk: &'a [u8],
}
impl<'a> Iterator for ByteIter<'a> {
type Item = Cow<'a, [u8]>;
fn next(&mut self) -> Option<Self::Item> {
Some(Cow::from(self.chunk))
}
}
struct StrIter<'a> {
inner: ByteIter<'a>,
}
impl<'a> Iterator for StrIter<'a> {
type Item = Cow<'a, str>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|cow| match cow {
Cow::Borrowed(slice) => Cow::from(unsafe { std::str::from_utf8_unchecked(slice) }),
Cow::Owned(vec) => Cow::from(unsafe { String::from_utf8_unchecked(vec) }),
})
}
}
1 Like
system
Closed
April 17, 2020, 3:52pm
4
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.