[英]Why Rust reset some variables after a loop?
我前段時間讀完了 Rust Programming Languange,為了自學 Rust,我正在創建一個簡單的 http 服務器。
在旨在解析&[u8]
並創建HttpRequest
object 的 function 中,我注意到應該解析標頭的循環實際上沒有更新一些用於跟蹤解析的 state 的變量:
pub fn parse_request(buffer: &[u8]) -> Result<HttpRequest, &'static str> {
let (mut line, mut curr_req_reader_pos) = next_req_line(buffer, 0);
let (method, path, version) = parse_method_path_and_version(&line)?;
let (line, curr_req_reader_pos) = next_req_line(buffer, curr_req_reader_pos);
//eprintln!("--- got next line: {}, {} ---", curr_req_reader_pos, String::from_utf8_lossy(line));
let mut headers = vec![];
let mut lel = 0;
while line.len() > 0 {
//eprintln!("LOOP");
let header = parse_header(&line);
eprintln!("--- parsed header: {} ---", String::from_utf8_lossy(line));
headers.push(header);
let (line, curr_req_reader_pos) = next_req_line(buffer, curr_req_reader_pos);
//eprintln!("--- got next line: {}, {} ---", curr_req_reader_pos, String::from_utf8_lossy(line));
let (line, curr_req_reader_pos) = next_req_line(buffer, curr_req_reader_pos);
//eprintln!("--- got next line: {}, {} ---", curr_req_reader_pos, String::from_utf8_lossy(line));
//eprintln!("LOOP");
lel += 10;
//break;
}
let (line, curr_req_reader_pos) = next_req_line(buffer, curr_req_reader_pos);
//eprintln!("--- got next line: {}, {} ---", curr_req_reader_pos, String::from_utf8_lossy(line));
//eprintln!("{}", lel);
let has_body;
match method.as_ref() {
"POST" | "PUT" | "PATCH" => has_body = true,
_ => has_body = true
};
let body;
if has_body {
let (line, curr_req_reader_pos) = next_req_line(buffer, curr_req_reader_pos);
body = String::from_utf8_lossy(line).to_string();
} else {
body = String::new();
}
Ok(HttpRequest {
method,
path,
version,
headers,
has_body,
body
})
}
還有針對每種方法的測試:
#[test]
fn test_next_req_line() {
let req = "GET / HTTP/1.1\r\nContent-Length: 3\r\n\r\n\r\n\r\nlel".as_bytes();
let (mut lel, mut pos) = next_req_line(req, 0);
assert_eq!("GET / HTTP/1.1", String::from_utf8_lossy(lel));
assert!(lel.len() > 0);
assert_eq!(16, pos);
let (lel, pos) = next_req_line(req, pos);
assert_eq!("Content-Length: 3", String::from_utf8_lossy(lel));
assert!(lel.len() > 0);
assert_eq!(35, pos);
let (lel, pos) = next_req_line(req, pos);
assert_eq!("", String::from_utf8_lossy(lel));
assert!(lel.len() == 0);
assert_eq!(37, pos);
let (lel, pos) = next_req_line(req, pos);
assert_eq!("", String::from_utf8_lossy(lel));
assert!(lel.len() == 0);
let (lel, pos) = next_req_line(req, pos);
assert_eq!("", String::from_utf8_lossy(lel));
assert!(lel.len() == 0);
let (lel, pos) = next_req_line(req, pos);
assert_eq!("lel", String::from_utf8_lossy(lel));
assert!(lel.len() == 3);
}
#[test]
fn test_parse_request() {
let mut request = String::from("GET / HTTP/1.1\r\n");
request.push_str("Content-Length: 3\r\n");
request.push_str("\r\n");
request.push_str("lel");
let request = request.as_bytes();
match parse_request(&request) {
Ok(http_request) => {
assert_eq!(http_request.method, "GET");
assert_eq!(http_request.path, "/");
assert_eq!(http_request.version, "HTTP/1.1");
},
Err(_) => {
println!("Failed");
}
}
}
注釋行只是為了說明發生了什么,這就是我看到這個 output 的地方:
Finished test [unoptimized + debuginfo] target(s) in 0.53s
Running target/debug/deps/rweb-6bbc2a3130f7e3d9
running 4 tests
test http::testing::test_next_req_line ... ok
test http::testing::test_parse_header ... ok
test http::testing::test_parse_method_path_and_version ... ok
--- parsed method path version ---
--- got next line: 35, Content-Length: 3 ---
LOOP
--- parsed header: Content-Length: 3 ---
--- got next line: 37, ---
--- got next line: 39, lel ---
LOOP
--- got next line: 37, ---
10
test http::testing::test_parse_request ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
似乎while
循環沒有重新分配line
和curr_req_reader_pos
變量,但對我來說,期望循環會更新這些變量並解析每個 header 是完全合理的。但是,它在循環外工作得很好,任何人都可以在測試中看到。
我無法弄清楚為什么我目前對 Rust 的理解會發生這種情況,為什么會發生這種情況?
您不是在循環中“重新分配”變量,您創建的新變量會暫時隱藏外部變量,然后在迭代結束時從 scope 中創建 go。
這是關於簡化偽代碼中發生的事情的說明:
let x0 = 0
{
let x1 = x0 + 1 // original x gets shadowed, x = 1
let x2 = x1 + 1 // x1 gets shadowed, x = 2
} // both x1 and x2 go out of scope
let x1 = x0 + 1 // x = 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.