1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::common::{CommonProperties, StixObject};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "snake_case")]
9pub struct Incident {
10 #[serde(flatten)]
11 pub common: CommonProperties,
12
13 pub name: String,
14 pub description: Option<String>,
15}
16
17impl Incident {
18 pub fn builder() -> IncidentBuilder {
19 IncidentBuilder::default()
20 }
21}
22
23#[derive(Debug, Default)]
24pub struct IncidentBuilder {
25 name: Option<String>,
26 description: Option<String>,
27 created_by_ref: Option<String>,
28}
29
30impl IncidentBuilder {
31 pub fn name(mut self, n: impl Into<String>) -> Self {
32 self.name = Some(n.into());
33 self
34 }
35 pub fn description(mut self, d: impl Into<String>) -> Self {
36 self.description = Some(d.into());
37 self
38 }
39 pub fn created_by_ref(mut self, r: impl Into<String>) -> Self {
40 self.created_by_ref = Some(r.into());
41 self
42 }
43
44 pub fn build(self) -> Result<Incident, super::BuilderError> {
45 let name = self.name.ok_or(super::BuilderError::MissingField("name"))?;
46 let common = CommonProperties::new("incident", self.created_by_ref);
47 Ok(Incident {
48 common,
49 name,
50 description: self.description,
51 })
52 }
53}
54
55impl StixObject for Incident {
56 fn id(&self) -> &str {
57 &self.common.id
58 }
59 fn type_(&self) -> &str {
60 &self.common.r#type
61 }
62 fn created(&self) -> DateTime<Utc> {
63 self.common.created
64 }
65}
66
67impl From<Incident> for crate::StixObjectEnum {
68 fn from(i: Incident) -> Self {
69 crate::StixObjectEnum::Incident(i)
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use serde_json::Value;
77
78 #[test]
79 fn incident_builder_and_serialize() {
80 let inc = Incident::builder()
81 .name("Test Incident")
82 .description("desc")
83 .build()
84 .unwrap();
85 let s = serde_json::to_string(&inc).unwrap();
86 let v: Value = serde_json::from_str(&s).unwrap();
87 assert_eq!(v.get("type").and_then(Value::as_str).unwrap(), "incident");
88 assert_eq!(
89 v.get("name").and_then(Value::as_str).unwrap(),
90 "Test Incident"
91 );
92 }
93}