Skip to main content

stix_rs/sdos/
incident.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::common::{CommonProperties, StixObject};
5
6/// Incident SDO (STIX 2.1 minimal stub)
7#[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}