Jon*_*hon 3 iterator lifetime ownership rust borrow-checker
我正在尝试构建一种 HTTP Web 服务器作为学习练习,但在尝试使用 for 循环(通过实现IntoIterator)使我的其中一个类型可迭代时遇到了麻烦。
我创建了一个数据结构,其中我有一个Response对象(旨在模拟 HTTP 响应),并且包含一个Headers对象(旨在模拟 HTTP 响应标头),并且包含HashMap<String, String>,表示实际标头值:
use std::collections::HashMap;
struct Headers {
headers: HashMap<String, String>,
}
impl Headers {
pub fn new(headers: HashMap<String, String>) -> Self {
Self { headers }
}
}
struct Response {
headers: Headers,
}
impl Response {
pub fn new(headers: Headers) -> Self {
Self { headers }
}
pub fn headers(&self) -> &Headers {
&self.headers
}
}
Run Code Online (Sandbox Code Playgroud)
注意:该headers方法返回一个不可变的引用,因为我只想读取这些值。理想情况下,我不想复制/克隆标题以便可以读取它们。
我想要做的是这样的:
fn main() {
// just creating an example here
let mut headers = HashMap::new();
headers.insert("foo".to_string(), "one".to_string());
headers.insert("bar".to_string(), "two".to_string());
let response = Response::new(Headers::new(headers));
// this is what I'm aiming for:
for (key, value) in response.headers() {
println!("{}: {}", key, value);
}
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了很多方法来使其正常工作,但到目前为止我都失败了。到目前为止,我最接近的是实现IntoIteratorfor&Headers然后调用into_iter()哈希图:
impl IntoIterator for &Headers {
type Item = (String, String);
type IntoIter = IntoIter<String, String>;
fn into_iter(self) -> Self::IntoIter {
self.headers.into_iter()
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这会导致错误:
无法移出
self.headers共享引用后面的内容
我尝试四处搜索,发现了许多类似的 StackOverflow 问题,但似乎没有一个能回答我的确切问题。
谢谢。
您现在正在做的是委托IntoIterator实施HashMap<String, String>. 但是您需要委托给 的实现,IntoIterator因为&HashMap<String, String>您无法获得self.headerswhenself的引用的拥有版本。
不过,谢天谢地,这是一个简单的修复:
// Just giving this type a concise name so we can reference it easyily later
type HeaderMap = HashMap<String, String>;
impl<'h> IntoIterator for &'h Headers {
// Here we just tell Rust to use the types we're delegating to.
// This is just (&'h String, &'h String)
type Item = <&'h HeaderMap as IntoIterator>::Item;
type IntoIter = <&'h HeaderMap as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
// Now just call `into_iter` on the correct thing
(&self.headers).into_iter()
// self.headers.iter() would work just as well here
}
}
Run Code Online (Sandbox Code Playgroud)