I am trying to create a struct that takes an input string (and takes ownership of it), does some calculations, then returns a struct that contains the string and some precomputed slices of the string.
Something like:
pub async fn read_file<'a>(path: &Path) -> Result<MyString<'a>> {
let contents = tokio::fs::read_to_string(path).await?;
let slice = costly_search(&contents);
Ok(MyString::new(contents, slice))
}
pub struct MyString<'a>
{
slice: &'a str,
string: String,
}
impl<'a> MyString<'a> {
pub fn new(string: String, slice: &'a str) -> MyString<'a> {
MyString { string, slice }
}
pub fn get_slice(&self) -> &str {
self.slice
}
}
The file contents
can be large so I don't want to copy it. The function costly_search
can take some time to compute, but always returns a slice of its input; that slice is also large so I don't want to copy that slice into a new String. This is also simplified; I will have multiple slices of the input string in the struct and consumers can pass the whole thing around and use the precomputed slices as they need.
When I try to compile this I get:
`contents` does not live long enough
borrowed value does not live long enough
utils.rs(43, 31): borrowed value does not live long enough
utils.rs(45, 1): `contents` dropped here while still borrowed
Is there a way to accomplish what I'm trying to do?
In Rust, we can use the trim() method of a string to remove the whitespace characters around that string. This method removes the leading and trailing whitespace characters of a given string.
A string slice is a reference to part of a String , and it looks like this: let s = String::from("hello world"); let hello = &s[0.. 5]; let world = &s[6.. 11]; Rather than a reference to the entire String , hello is a reference to a portion of the String , specified in the extra [0..
In summary, use String if you need owned string data (like passing strings to other threads, or building them at runtime), and use &str if you only need a view of a string.
Can you make that costly_search()
return start & end indexes into the string instead and pass those on to MyString::new()
? Then you can create a new slice every time like
fn get_slice(&self) -> &str {
&self.contents[self.start..self.end]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With