How to map Cow<'a, [u8]> to &'a str

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

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.