Rust match Option type get error use of moved value

Advertisements

I’m new to rust and I found piece of code below:

use std::collections::HashMap;
use std::io::{Result, Write};

#[derive(Debug, PartialEq, Clone)]
pub struct HttpResponse<'a> {
    version: &'a str,
    status_code: &'a str,
    status_text: &'a str,
    headers: Option<HashMap<&'a str, &'a str>>,
    body: Option<String>,
}


impl<'a> Default for HttpResponse<'a> {
    fn default() -> Self {
        Self {
            version: "HTTP/1.1".into(),
            status_code: "200".into(),
            status_text: "OK".into(),
            headers: None,
            body: None,
        }
    }
}

impl<'a> HttpResponse<'a> {
    pub fn new(
        status_code: &'a str,
        headers: Option<HashMap<&'a str, &'a str>>,
        body: Option<String>,
    ) -> HttpResponse<'a> {
        let mut response: HttpResponse<'a> = HttpResponse::default();
        if status_code != "200" {
            response.status_code = status_code;
        };

        response.headers = match headers {
            Some(_h) => headers, // got error here: Use of moved value 
            // use of partially moved value: `headers` [E0382] 
            // value used here after partial move Note: partial move occurs because value has type `HashMap<&str, &str>`, 
            // which does not implement the `Copy` trait
            None => {
                let mut h = HashMap::new();
                h.insert("Content-Type", "text/html");
                Some(h)
            }
        };

        response.status_text = match response.status_code {
            "200" => "OK".into(),
            "400" => "Bad Request".into(),
            "404" => "Not Found".into(),
            "500" => "Internal Server Error".into(),
            _ => "Not Found".into(),
        };
        response.body = body;

        response
    }
}
error[E0382]: use of partially moved value: `headers`
  --> src/lib.rs:38:25
   |
38 |             Some(_h) => headers, // got error here: Use of moved value 
   |                  --     ^^^^^^^ value used here after partial move
   |                  |
   |                  value partially moved here
   |
   = note: partial move occurs because value has type `HashMap<&str, &str>`, which does not implement the `Copy` trait

I don’t know why I got the "Use of moved value", I think the way called "moved" should be something like this:

    let s1 = String::from("Hello,World");
    let s2 = s1;

or you pass variable as parameter to some function.

so, could some explain why I got this error? what is moved here? and why if we change the code with reference, the error disappear(nothing moved?)

response.headers = match &headers { 

>Solution :

matching something moves it, if matching the object itself. This is just how Rust works. Rust objects aren’t copyable by default, so destructuring operations (like if let or match) destroy the original object to gain access to its contents.

This is easily fixable by matching a reference instead:

response.headers = match &headers {
    Some(_h) => headers,
    None => {
        let mut h = HashMap::new();
        h.insert("Content-Type", "text/html");
        Some(h)
    }
};

Alternatively (and probably preferredly), use the built-in function for exactly your purpose:

response.headers = headers.or_else(|| {
    let mut h = HashMap::new();
    h.insert("Content-Type", "text/html");
    Some(h)
});

Or even shorter:

response.headers = headers.or_else(|| Some(HashMap::from([("Content-Type", "text/html")])));

Leave a ReplyCancel reply