Skip to main content

stix_rs/sdos/
malware_analysis.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::common::{CommonProperties, StixObject};
5use crate::sdos::BuilderError;
6
7/// Malware Analysis SDO
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub struct MalwareAnalysis {
11    #[serde(flatten)]
12    pub common: CommonProperties,
13    pub product: Option<String>,
14    pub version: Option<String>,
15    pub analysis_engine_version: Option<String>,
16    pub result: Option<String>,
17}
18
19impl MalwareAnalysis {
20    pub fn builder() -> MalwareAnalysisBuilder {
21        MalwareAnalysisBuilder::default()
22    }
23}
24
25#[derive(Debug, Default)]
26pub struct MalwareAnalysisBuilder {
27    product: Option<String>,
28    version: Option<String>,
29    analysis_engine_version: Option<String>,
30    result: Option<String>,
31    created_by_ref: Option<String>,
32}
33
34impl MalwareAnalysisBuilder {
35    pub fn product(mut self, p: impl Into<String>) -> Self {
36        self.product = Some(p.into());
37        self
38    }
39
40    pub fn version(mut self, v: impl Into<String>) -> Self {
41        self.version = Some(v.into());
42        self
43    }
44
45    pub fn analysis_engine_version(mut self, v: impl Into<String>) -> Self {
46        self.analysis_engine_version = Some(v.into());
47        self
48    }
49
50    pub fn result(mut self, r: impl Into<String>) -> Self {
51        self.result = Some(r.into());
52        self
53    }
54
55    pub fn created_by_ref(mut self, r: impl Into<String>) -> Self {
56        self.created_by_ref = Some(r.into());
57        self
58    }
59
60    pub fn build(self) -> Result<MalwareAnalysis, BuilderError> {
61        let common = CommonProperties::new("malware-analysis", self.created_by_ref);
62        Ok(MalwareAnalysis {
63            common,
64            product: self.product,
65            version: self.version,
66            analysis_engine_version: self.analysis_engine_version,
67            result: self.result,
68        })
69    }
70}
71
72impl StixObject for MalwareAnalysis {
73    fn id(&self) -> &str {
74        &self.common.id
75    }
76
77    fn type_(&self) -> &str {
78        &self.common.r#type
79    }
80
81    fn created(&self) -> DateTime<Utc> {
82        self.common.created
83    }
84}
85
86impl From<MalwareAnalysis> for crate::StixObjectEnum {
87    fn from(m: MalwareAnalysis) -> Self {
88        crate::StixObjectEnum::MalwareAnalysis(m)
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use serde_json::Value;
96
97    #[test]
98    fn malware_analysis_builder() {
99        let ma = MalwareAnalysis::builder()
100            .product("AV")
101            .version("1.0")
102            .result("clean")
103            .build()
104            .unwrap();
105
106        assert_eq!(ma.product.as_deref(), Some("AV"));
107        assert_eq!(ma.common.r#type, "malware-analysis");
108    }
109
110    #[test]
111    fn malware_analysis_serialize() {
112        let ma = MalwareAnalysis::builder()
113            .product("AV")
114            .version("1.0")
115            .result("clean")
116            .build()
117            .unwrap();
118
119        let s = serde_json::to_string(&ma).unwrap();
120        let v: Value = serde_json::from_str(&s).unwrap();
121        assert_eq!(
122            v.get("type").and_then(Value::as_str).unwrap(),
123            "malware-analysis"
124        );
125    }
126}