stix-rs 0.1.0

STIX 2.1 types and helpers for Rust
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct SoftwarePackage {
    pub name: Option<String>,
    pub version: Option<String>,
    pub cpe: Option<String>,
    pub created: Option<DateTime<Utc>>,
    #[serde(flatten)]
    pub custom_properties: std::collections::HashMap<String, serde_json::Value>,
}

impl SoftwarePackage {
    pub fn builder() -> SoftwarePackageBuilder {
        SoftwarePackageBuilder::default()
    }
}

#[derive(Debug, Default)]
pub struct SoftwarePackageBuilder {
    name: Option<String>,
    version: Option<String>,
    cpe: Option<String>,
    created: Option<DateTime<Utc>>,
    custom_properties: std::collections::HashMap<String, serde_json::Value>,
}

impl SoftwarePackageBuilder {
    pub fn name(mut self, n: impl Into<String>) -> Self {
        self.name = Some(n.into());
        self
    }
    pub fn version(mut self, v: impl Into<String>) -> Self {
        self.version = Some(v.into());
        self
    }
    pub fn cpe(mut self, c: impl Into<String>) -> Self {
        self.cpe = Some(c.into());
        self
    }
    pub fn created(mut self, d: DateTime<Utc>) -> Self {
        self.created = Some(d);
        self
    }
    pub fn property(mut self, k: impl Into<String>, val: impl Into<serde_json::Value>) -> Self {
        self.custom_properties.insert(k.into(), val.into());
        self
    }
    pub fn build(self) -> SoftwarePackage {
        SoftwarePackage {
            name: self.name,
            version: self.version,
            cpe: self.cpe,
            created: self.created,
            custom_properties: self.custom_properties,
        }
    }
}

impl From<SoftwarePackage> for crate::StixObjectEnum {
    fn from(s: SoftwarePackage) -> Self {
        crate::StixObjectEnum::SoftwarePackage(s)
    }
}

#[cfg(test)]
mod tests {
    use serde_json::json;

    #[test]
    fn software_package_serde() {
        let v = json!({"type": "software-package", "name": "pkg", "version": "1.2.3"});
        let obj: crate::StixObjectEnum =
            serde_json::from_value(v).expect("deserialize into StixObjectEnum");
        match obj {
            crate::StixObjectEnum::SoftwarePackage(sp) => {
                assert_eq!(sp.name.unwrap(), "pkg");
                assert_eq!(sp.version.unwrap(), "1.2.3");
            }
            _ => panic!("expected SoftwarePackage variant"),
        }
    }
}