Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to return a struct whose property has a type of &str from a function in rust?

I am trying to do the following

// Just removes redundant white space while also splitting the string
// with a whitespace.
fn split_whitespace(string: &str) -> Vec<&str> {
    let words: Vec<&str> = string
        .split_whitespace()
        .filter(|&word| word != "")
        .collect();
    words
}

pub fn get_websites_from_hosts(hosts_path: &Path) -> Result<Vec<Website>, std::io::Error> {
    let hosts_string = read_to_string(hosts_path)?;

    let result: Vec<Website> = hosts_string
        .lines()
        .filter(|&line| split_whitespace(&line.to_owned()).len() == 2)
        .map(|line| {
            let ip_domain = split_whitespace(&line.to_owned());
            Website {
                domain_name: ip_domain[1], // This won't work because it is refering hosts_string which is a local variable of the function
                redirect_ip: ip_domain[0], // the same case with this one.
                is_blocked: true,
                hosts_path,
            }
        })
        .collect();

    Ok(result)
}

What I want to achieve is to successfully return the Website struct while probably not editing the struct declaration.

And here is the Website struct declaration

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#[derive(Debug, Clone)]
pub struct Website<'a> {
    pub domain_name: &'a str,
    pub redirect_ip: &'a str,
    pub is_blocked: bool,
    pub hosts_path: &'a Path,
}

And here is the error

error[E0515]: cannot return value referencing temporary value
  --> src/parser.rs:21:13
   |
20 |               let ip_domain = split_whitespace(&line.to_owned());
   |                                                 --------------- temporary value created here
21 | /             Website {
22 | |                 domain_name: ip_domain[1],
23 | |                 redirect_ip: ip_domain[0],
24 | |                 is_blocked: true,
25 | |                 hosts_path,
26 | |             }
   | |_____________^ returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
error: could not compile `website-blocker` due to previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `website-blocker` due to previous error

I would love a deep explanation and general tips to use when encountering this and the like problems

>Solution :

The &str references in your struct refer to segments of the string returned by read_to_string. That string (hosts_string) is dropped and deallocated at the end of fn get_websites_from_hosts, so if you could return references to it, they would be dangling. Rust prevents you from doing that.

Instead, you’ll need to either move the read_to_string outside that function, and pass the string in as an &str or change your struct to hold owned values like String, IpAddr, etc.

#[derive(Debug, Clone)]
pub struct Website<'a> {
    pub domain_name: String,
    pub redirect_ip: IpAddr,
    pub is_blocked: bool,
    pub hosts_path: &'a Path,
}

If you want to avoid some String allocations, you could use a "small-string optimization" library like compact_str

#[derive(Debug, Clone)]
pub struct Website<'a> {
    // Stores a domain name of up to 24 bytes in place,
    // without an extra heap allocation
    pub domain_name: CompactString,
    pub redirect_ip: IpAddr,
    pub is_blocked: bool,
    pub hosts_path: &'a Path,
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading