Help required with borrowing

I've the below code that is reading from csv file, and saving the data in Vec, reading is done correctly, but panic while trying saving it in the vec INs:

use std::error::Error;
use std::io;
use std::process;
use std::path::Path;

#[macro_use] extern crate serde_derive;

#[derive(Clone, Debug, Deserialize)]
struct INs<'a> {
    item: &'a str,
    date: &'a str,
    batch: &'a str,
    quantity: u64,
}

fn main() {
    let mut ins = Inventory::new();
    let file_path_ins = Path::new("src/ins.csv");
    let mut rdr_ins = csv::ReaderBuilder::new()
        .has_headers(true)
        .delimiter(b',')
        .from_path(file_path_ins).unwrap();

    for result in rdr_ins.records() {
         let record: INs = result.unwrap().deserialize(None).unwrap();
          ins.push(INs { item: record.item, date: record.date,
                     batch: record.batch, quantity: record.quantity, });
    };
// Tried also:
 /*   for result in rdr_ins.records() {
        match result.unwrap().deserialize::<INs>(None){
            Ok(record) => {
                         println!("{:?}", record);  // This alone is ok, with the lines under it panic
                     //    ins.push(INs { item: record.item, date: record.date,
                     //            batch: record.batch, quantity: record.quantity, });
            },
            Err(e) => {
                println!("Error: {:?}", e);
            },
        }
    }
*/

}

I got the below error, and do not understand where the compiler want me to use let as shown below:

error[E0716]: temporary value dropped while borrowed
   --> src\main.rs:100:28
    |
100 |          let record: INs = result.unwrap().deserialize(None).unwrap();
    |                            ^^^^^^^^^^^^^^^                           - temporary value is freed at the end of this statement
    |                            |
    |                            creates a temporary which is freed while still in use
101 |           ins.push(INs { item: record.item, date: record.date,
    |                                ----------- borrow later used here
    |
    = note: consider using a `let` binding to create a longer lived value

Your csv crate is not reading the entire file into memory — it is destroying memory as it goes along and have been parsed. This means that your INs type can't have references into the file. You should take ownership of the strings instead.

Thanks, it worked by changing the:

#[derive(Clone, Debug, Deserialize)]
struct INs<'a> {
    item: &'a str,
    date: &'a str,
    batch: &'a str,
    quantity: u64,
}

to:

#[derive(Clone, Debug, Deserialize)]
struct INs {
    item: String,
    date: String,
    batch: String,
    quantity: u64,
}

Is this the correct solution? It looks I still not clear about &'a str and String, which one is better to use, and which one to use where!

The difference between &str and String is whether it owns the string. When using String, your object is its own independent thing, but when using &str, the actual string data is stored in some other variable somewhere else, and that other variable can't be modified while the &str exists.

So if INs is to contain a &str, you have to answer the question "well if the string isn't stored in INs, then where is it stored?". And you have to make sure that where you store it stays alive and is not modified while the &str exists.

When you use a string constant in your code, the variable that actually has the string data is an immutable global variable. Since immutable globals exist forever, the &str can be static (static means it can live forever).

2 Likes

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