use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::common::{CommonProperties, StixObject};
use crate::sdos::BuilderError;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct MalwareAnalysis {
#[serde(flatten)]
pub common: CommonProperties,
pub product: Option<String>,
pub version: Option<String>,
pub analysis_engine_version: Option<String>,
pub result: Option<String>,
}
impl MalwareAnalysis {
pub fn builder() -> MalwareAnalysisBuilder {
MalwareAnalysisBuilder::default()
}
}
#[derive(Debug, Default)]
pub struct MalwareAnalysisBuilder {
product: Option<String>,
version: Option<String>,
analysis_engine_version: Option<String>,
result: Option<String>,
created_by_ref: Option<String>,
}
impl MalwareAnalysisBuilder {
pub fn product(mut self, p: impl Into<String>) -> Self {
self.product = Some(p.into());
self
}
pub fn version(mut self, v: impl Into<String>) -> Self {
self.version = Some(v.into());
self
}
pub fn analysis_engine_version(mut self, v: impl Into<String>) -> Self {
self.analysis_engine_version = Some(v.into());
self
}
pub fn result(mut self, r: impl Into<String>) -> Self {
self.result = Some(r.into());
self
}
pub fn created_by_ref(mut self, r: impl Into<String>) -> Self {
self.created_by_ref = Some(r.into());
self
}
pub fn build(self) -> Result<MalwareAnalysis, BuilderError> {
let common = CommonProperties::new("malware-analysis", self.created_by_ref);
Ok(MalwareAnalysis {
common,
product: self.product,
version: self.version,
analysis_engine_version: self.analysis_engine_version,
result: self.result,
})
}
}
impl StixObject for MalwareAnalysis {
fn id(&self) -> &str {
&self.common.id
}
fn type_(&self) -> &str {
&self.common.r#type
}
fn created(&self) -> DateTime<Utc> {
self.common.created
}
}
impl From<MalwareAnalysis> for crate::StixObjectEnum {
fn from(m: MalwareAnalysis) -> Self {
crate::StixObjectEnum::MalwareAnalysis(m)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Value;
#[test]
fn malware_analysis_builder() {
let ma = MalwareAnalysis::builder()
.product("AV")
.version("1.0")
.result("clean")
.build()
.unwrap();
assert_eq!(ma.product.as_deref(), Some("AV"));
assert_eq!(ma.common.r#type, "malware-analysis");
}
#[test]
fn malware_analysis_serialize() {
let ma = MalwareAnalysis::builder()
.product("AV")
.version("1.0")
.result("clean")
.build()
.unwrap();
let s = serde_json::to_string(&ma).unwrap();
let v: Value = serde_json::from_str(&s).unwrap();
assert_eq!(
v.get("type").and_then(Value::as_str).unwrap(),
"malware-analysis"
);
}
}