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 :
match
ing 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 match
ing 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")])));