在Rust中迭代结构体

4

我是一名初学者,之前只接触过JS/TS,现在想学习Rust。

我已经看到了其他类似的问题,例如:如何在Rust中迭代结构体的元素? 但是它们没有给我一个真正的答案。

我想在Rust中遍历结构体的键和值。

在JS/TS中,可以这样实现:

const o = {
    a: "hello",
    b: "world"
};

const keys = Object.keys(o);
const values = Object.values(o);

// now loop over them 

这样的东西在Rust中该如何实现?

我正在使用Serde将配置yaml文件解析成结构体。


#[derive(Deserialize, Debug, Clone)]
pub struct Config {
    pub headers: Headers,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Headers {
    #[serde(rename = "Content-Security-Policy")]
    pub content_security_policy: String,
    #[serde(rename = "x-frame-options")]
    pub x_frame_options: String,
    #[serde(rename = "x-content-type-options")]
    pub x_content_type_options: String,
    #[serde(rename = "x-permitted-cross-domain-policies")]
    pub x_permitted_cross_domain_policies: String,
    #[serde(rename = "x-download-options")]
    pub x_download_options: String,
    #[serde(rename = "x-xss-protection")]
    pub x_xss_protection: String,
    #[serde(rename = "referrer-policy")]
    pub referrer_policy: String,
    #[serde(rename = "Strict-Transport-Security")]
    pub strict_transport_security: String,
    #[serde(rename = "feature-policy")]
    pub feature_policy: String,
    #[serde(rename = "Cache-Control")]
    pub cache_control: String,
}


但是这并没有实现 .iter() 函数,我在搜索中也没有找到解决方案。

1
这回答您的问题吗?如何在 Rust 中迭代结构体元素? - Chayim Friedman
不,这只会引导我们进入另一个离答案更远的问题。 - firstdorsal
3
在Rust中,无法迭代结构体。但是,由于您已经在使用serde,因此可以使用它将您的结构体转换为可迭代的内容,例如HashMap<String, String>。请参见这里 - Caesar
它非常明确地表明:“不行。你必须自己实现,或者找一个宏/编译器插件来帮你做。” - Chayim Friedman
2个回答

4

感谢Caesar

我尝试了以下方法:


use serde::{Deserialize, Serialize};

#[derive(Deserialize, Debug, Clone, Serialize)]
pub struct Config {
    pub headers: Headers,
}

#[derive(Deserialize, Debug, Clone, Serialize)]
pub struct Headers {
    #[serde(rename = "Content-Security-Policy")]
    pub content_security_policy: String,
    #[serde(rename = "x-frame-options")]
    pub x_frame_options: String,
    #[serde(rename = "x-content-type-options")]
    pub x_content_type_options: String,
    #[serde(rename = "x-permitted-cross-domain-policies")]
    pub x_permitted_cross_domain_policies: String,
    #[serde(rename = "x-download-options")]
    pub x_download_options: String,
    #[serde(rename = "x-xss-protection")]
    pub x_xss_protection: String,
    #[serde(rename = "referrer-policy")]
    pub referrer_policy: String,
    #[serde(rename = "Strict-Transport-Security")]
    pub strict_transport_security: String,
    #[serde(rename = "feature-policy")]
    pub feature_policy: String,
    #[serde(rename = "Cache-Control")]
    pub cache_control: String,
}

let iterable_headers: HashMap<String, String> =
 serde_yaml::from_value(serde_yaml::to_value(&config.headers).unwrap()).unwrap();

for header in &iterable_headers {
    res = res.header(header.0, header.1);
}


2
你可以使用struct_iterable crate。
use struct_iterable::Iterable;
            
#[derive(Iterable)]
struct MyStruct {
    field1: u32,
    field2: String,
    field3: Option<String>,
    // etc.
}
    
let my_instance = MyStruct {
    field1: 42,
    field2: "Hello, world!".to_string(),
    field3: Some("Hello, world!".to_string()),
};
    
for (field_name, field_value) in my_instance.iter() {
    if let Some(string_opt) = field_value.downcast_ref::<Option<String>>() {
        if let Some(string) = string_opt.as_deref() {
            println!("{} optional String: {:?}", field_name, field_value);
        }
    }
    println!("{}: {:?}", field_name, field_value);
}

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