Return list of strings created in a function

Hello,
I'm new to Rust and I have an issue with a function I'm trying to create :

fn wayback_pattern(pattern: String) -> Result<Lines, reqwest::Error> {
    let url  = format!("http://web.archive.org/cdx/search/cdx?url={}&output=text&fl=original&collapse=urlkey",pattern);
    reqwest::get(url.as_str())?.text()?.lines()
}

The error I have is

error[E0106]: missing lifetime specifier

I would like to know what is the good way to return a variable created in the function, I searched a lot but i'm stuck for hours with this error ...

Thank you.

The definition of the type Lines is:

pub struct Lines<'a>(SomeIterator<'a>);

It's not important which exact iterator is used inside, but it has a lifetime specifier! Now, what does this mean?

It means that a Lines has a reference to some data somewhere else. In this case the string. This means that you could keep on using the string after inspecting it using the Lines iterator. Note that since the string you are iterating over is created inside the function, you cannot return a reference to it, which is the root of the problem.

Ultimately, the Lines does not own the data, so it must be owned somewhere else, but this is currently inside the function, and since it is not returned it will be destroyed at the end of the function.

There are two solutions:

  1. Return a String instead of a Lines and let the caller split it up into lines.
  2. Return a Vec<String> where each string is a line.

The reason that both of these work is that they return owned data. A String owns the data inside, and so does a Vec. Note that you can use lines to create the vector:

fn wayback_pattern(pattern: String) -> Result<Vec<String>, reqwest::Error> {
    let url  = format!("http://web.archive.org/cdx/search/cdx?url={}&output=text&fl=original&collapse=urlkey",pattern);
    Ok(reqwest::get(url.as_str())?
        .text()?
        .lines()
        .map(|s| s.to_string())
        .collect())
}

The map here is necessary because each line is of type &str and therefore borrows the data, so I convert it using to_string, which creates a String that owns the data.

1 Like

Thank you !
I finally made it but I didn't understand clearly before your answer so thanks a lot !
here is what i made :

fn wayback_pattern(pattern: String) -> Vec<String> {
    let url  = format!("http://web.archive.org/cdx/search/cdx?url={}&output=text&fl=original&collapse=urlkey",pattern);
    let response = reqwest::get(url.as_str());
    match response{
        Ok(mut t) => {
            match t.text(){
                Ok(r) => r.lines().map(|item| item.to_owned()).collect(),
                Err(e) => panic!("Error : {}",e),
            }
        },
        Err(e) => panic!("Error : {}",e),
    }