Rust:改变一个 Option 字段,它的包装值没有实现 Copy trait

Est*_*rai 1 rust

我有一个Message结构,它有一个字段,我想在调用方法时修改它。

这个Message结构有一个attachments字段,它是一个Option<Vec<Attachment>>.

我的目标是能够调用一个方法Message来将一个Attachment对象推送到attachments Vec.

#[derive(Debug, Serialize, Deserialize)]
pub struct Message {
    /// The verified sender email address
    #[serde(rename = "FromEmail")]
    pub from_email: String,
    /// The name of the sender
    #[serde(rename = "FromName")]
    pub from_name: String,
    /// The subject of the email
    #[serde(rename = "Subject")]
    pub subject: Option<String>,
    /// The raw text content of the email
    #[serde(rename = "Text-part")]
    pub text_part: String,
    /// The HTML content of the email
    #[serde(rename = "Html-part")]
    pub html_part: Option<String>,
    #[serde(rename = "Recipients")]
    pub recipients: Vec<Recipient>,
    #[serde(rename = "Attachments")]
    pub attachments: Option<Vec<Attachment>>,
    #[serde(rename = "Inline_attachments")]
    pub inline_attachments: Option<Vec<InlineAttachments>>,
}
Run Code Online (Sandbox Code Playgroud)

以下是我当前对将Attachment对象推送到 的方法的实现Option<Vec<Attachment>>

    pub fn attach(&mut self, attachment: Attachment) {
        // if theres no attachments already
        // initialize the attachments vector
        if self.attachments.is_none() {
            let mut attachments = Vec::new();

            attachments.push(attachment);
            self.attachments = Some(attachments);
        } else {
            // Where this is invalid as theres no `clone` for `Option<Vec<Attachment>>`

            let attachments = self.attachments.clone();

            attachments.push(attachment);
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是实现Attachment struct

use serde::{Deserialize, Serialize};

/// An email attachment
#[derive(Debug, Serialize, Deserialize)]
pub struct Attachment {
  #[serde(rename = "Content-type")]
  pub content_type: String,
  #[serde(rename = "Filename")]
  pub filename: String,
  pub content: String,
}
Run Code Online (Sandbox Code Playgroud)

问题出在else块上,其中attachents Option字段被解包,然后一个attachment对象被推送到Vec.

问题是Attachment无法实现Copy特征。

对于 Rust 中的此类场景,哪种方法是正确的?

提前致谢!

bk2*_*204 5

Option有各种各样的辅助方法可以在这里提供帮助。如果Vec有的话,你基本上想改变已经存在的那个,如果没有,创建一个并改变它。你可以用 来做到这一点Option::get_or_insert_with,它返回一个&mut Vec<Attachment>。这样,您就可以将项目推到最后。一个最小的可编译示例如下所示:

pub struct Message {
    pub attachments: Option<Vec<Attachment>>,
}

#[derive(Debug)]
pub struct Attachment {
    pub content_type: String,
    pub filename: String,
    pub content: String,
}

impl Message {
    pub fn attach(&mut self, attachment: Attachment) {
        self.attachments
            .get_or_insert_with(Vec::new)
            .push(attachment);
    }
}

fn main() {
    let mut m = Message { attachments: None };
    let a = Attachment {
        content_type: "application/json".into(),
        filename: "foo.json".into(),
        content: "{}".into(),
    };
    m.attach(a);
    assert_eq!(m.attachments.unwrap()[0].content, "{}");
}
Run Code Online (Sandbox Code Playgroud)

如果您在 if-else 情况下使用is_someor is_none(or, for Result, is_okor is_err),这通常表明您可能想要重新考虑您在做什么,因为这在 Rust 中通常不是很惯用的。通常,有一种辅助方法可以以更简单、更易于使用的方式完成您想要的操作。