将IntoIterator实现在包装HashMap的结构体引用上

3
我正在尝试构建一种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
    }
}

注意:`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);
    }
}

我尝试过的方法

我尝试了很多方法来使这个工作起来,但是到目前为止都失败了。我最接近成功的方法是为&Headers实现IntoIterator,然后在哈希映射上调用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()
    }
}

然而,这将导致错误:

无法移动超出共享引用 self.headers 的内容

我已经尝试过搜索并找到了很多类似的StackOverflow问题,但是没有一个能够完全回答我的问题。
谢谢。
1个回答

6
您现在正在将迭代操作委托给HashMap<String, String>IntoIterator实现。但是,当self是引用时,无法获取self.headers的所有权版本,因此需要将迭代操作委托给&HashMap<String, String>IntoIterator实现。
不过,这很容易解决:
// 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
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接