Rust borrow on certain line - see code

extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::fs::File;
use std::fs::OpenOptions;
#[derive(Serialize, Deserialize)]
enum rating {
    Extremely_poor,
    Bad,
    Normal,
    Good,
    Vwry_Good
}

#[derive(Serialize, Deserialize)]
struct Dvd {
    name: String,
    year: String,
    length: u16,
    certificate: u16,
    current_rating: rating,
    studio: String,
    director: String,
}

fn json_from_str( raw: &str) -> Dvd {
    serde_json::from_str(raw).unwrap()
}
fn str_from_json( dvd: &Dvd) -> String {
    serde_json::to_string(dvd).unwrap()
}

fn dvds_to_file(f: &String, d: Dvd) {
    let file = OpenOptions::new().append(true).open(f).unwrap();
    serde_json::to_writer(file, &d);
}

fn dvds_from_file(f: &String) -> Dvd {
    let file = File::open(f).unwrap();
    let deserialzed_json: Dvd = serde_json::from_reader(file).unwrap();
    deserialzed_json
}
fn main() {
    let rawdata = r#"
    {
        "name" : "La La Land",
        "year" : 2014,
        "cast" : "Emma Stone, Ryan Gosling",
        "length" : 128,
        "certificate" : 18,
        "current_rating" : rating::Extremely_Bad,
        "studio" : "NA",
        "director" : "NA",
    }"#;
    let rawdata2 = r#"
    {
        "name" : "Wreck it Ralph",
        "year" : -1,
        "cast" : "NA",
        "length" : -1,
        "certficate" 15,
        "current_rating" : rating::Very_Good,
        "studio" : "Walt Disney Studio",
        "director" : "NA",
       }"#;
    let rawdata3 = r#"
    {
        "name" : "Fast and Furious 9 - The Fast Saga"
        "year" : 2021,
        "cast" : "Vin Diesel, Michelle Rodriguez, John Cana, Jordana Brewster, Charlize Theron, Tyrese Gibson, Ludacris",
        "length" : "NA",
        "certificate" : "TBC",
        "current_rating" : rating::Good,
        "studio" : "NA",
        "director: "Justin Lee",
    }"#;
    let mut Dvds: Vec<Dvd> = Vec::new();
    let mut d: Dvd = json_from_str(rawdata);
    let mut d1: Dvd = json_from_str( rawdata2);
    let mut d2: Dvd = json_from_str( rawdata3);

    Dvds.push(d);
    Dvds.push( d1);
    Dvds.push( d2);

    let encoded = str_from_json(&d);

    println!("{}", encoded);

    let filename = String::from("file.json");
    for dvd in Dvds {
        dvds_to_file(&filename, dvd);
    }
    //dvds_to_file(&filename, d);

    d = dvds_from_file(&filename);
    println!("{}", str_from_json(&d));

}

The compiler says that I have borrowed on the line with this line of code
let encoded = str_from_json(&d); Please help.

Dvds.push(d); moves the ownership of the value in variable d into the vector stored in Dvds. Thus you can't use it anymore through d. That's the point of the ownership model: every value has exactly one owner that is responsible for freeing it — allowing multiple owners would lead to double free errors.

If you want to keep using d, then push a copy of it onto the vector, by .clone()-ing it.


By the way, Dvds is not an idiomatic name – in Rust, variables are usually written in lower_snake_case.

1 Like
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::fs::File;
use std::fs::OpenOptions;
#[derive(Serialize, Deserialize, Clone)]
enum rating {
    Extremely_poor,
    Bad,
    Normal,
    Good,
    Vwry_Good
}

#[derive(Serialize, Deserialize, Clone)]
struct Dvd {
    name: String,
    year: String,
    length: u16,
    certificate: u16,
    current_rating: rating,
    studio: String,
    director: String,
}

fn json_from_str( raw: &str) -> Dvd {
    serde_json::from_str(raw).unwrap()
}
fn str_from_json( dvd: &Dvd) -> String {
    serde_json::to_string(dvd).unwrap()
}

fn dvds_to_file(f: &String, d: Dvd) {
    let file = OpenOptions::new().append(true).open(f).unwrap();
    serde_json::to_writer(file, &d);
}

fn dvds_from_file(f: &String) -> Dvd {
    let file = File::open(f).unwrap();
    let deserialzed_json: Dvd = serde_json::from_reader(file).unwrap();
    deserialzed_json
}
fn main() {
    let rawdata = r#"
    {
        "name" : "La La Land",
        "year" : 2014,
        "cast" : "Emma Stone, Ryan Gosling",
        "length" : 128,
        "certificate" : 18,
        "current_rating" : rating::Extremely_Bad,
        "studio" : "NA",
        "director" : "NA",
    }"#;
    let rawdata2 = r#"
    {
        "name" : "Wreck it Ralph",
        "year" : -1,
        "cast" : "NA",
        "length" : -1,
        "certficate" 15,
        "current_rating" : rating::Very_Good,
        "studio" : "Walt Disney Studio",
        "director" : "NA",
       }"#;
    let rawdata3 = r#"
    {
        "name" : "Fast and Furious 9 - The Fast Saga"
        "year" : 2021,
        "cast" : "Vin Diesel, Michelle Rodriguez, John Cana, Jordana Brewster, Charlize Theron, Tyrese Gibson, Ludacris",
        "length" : "NA",
        "certificate" : "TBC",
        "current_rating" : rating::Good,
        "studio" : "NA",
        "director: "Justin Lee",
    }"#;
    let mut Dvds: Vec<Dvd> = Vec::new();
    let mut d: Dvd = json_from_str(rawdata);
    let mut d1: Dvd = json_from_str( rawdata2);
    let mut d2: Dvd = json_from_str( rawdata3);

    Dvds.push(d.clone());
    Dvds.push( d1.clone());
    Dvds.push( d2.clone());

    let encoded = str_from_json(&d);

    println!("{}", encoded);

    let filename = String::from("file.json");
    for dvd in &Dvds {
        dvds_to_file(&filename, dvd);
    }

    for dvd in &Dvds {
        let d = dvds_from_file( &filename);
        println!("{}", str_from_json( &d));
    }
    //dvds_to_file(&filename, d);

    d = dvds_from_file(&filename);
    println!("{}", str_from_json(&d));

}

Expected struct Dvd found &Dvd

Thanks for help.