use serde::{Deserialize, Serialize};
use crate::OCSF_VERSION;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Metadata {
pub version: String,
pub product: Product,
#[serde(skip_serializing_if = "Option::is_none")]
pub original_uid: Option<String>,
}
impl Metadata {
#[must_use]
pub fn clawdstrike(product_version: &str) -> Self {
Self {
version: OCSF_VERSION.to_string(),
product: Product::clawdstrike(product_version),
original_uid: None,
}
}
#[must_use]
pub fn with_original_uid(mut self, uid: impl Into<String>) -> Self {
self.original_uid = Some(uid.into());
self
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Product {
pub name: String,
pub uid: String,
pub vendor_name: String,
pub version: String,
}
impl Product {
#[must_use]
pub fn clawdstrike(version: &str) -> Self {
Self {
name: "ClawdStrike".to_string(),
uid: "clawdstrike".to_string(),
vendor_name: "Backbay Labs".to_string(),
version: version.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn metadata_clawdstrike() {
let m = Metadata::clawdstrike("0.1.3");
assert_eq!(m.version, "1.4.0");
assert_eq!(m.product.name, "ClawdStrike");
assert_eq!(m.product.uid, "clawdstrike");
assert_eq!(m.product.vendor_name, "Backbay Labs");
assert_eq!(m.product.version, "0.1.3");
assert!(m.original_uid.is_none());
}
#[test]
fn metadata_with_original_uid() {
let m = Metadata::clawdstrike("0.1.3").with_original_uid("evt-123");
assert_eq!(m.original_uid.as_deref(), Some("evt-123"));
}
#[test]
fn metadata_roundtrip() {
let m = Metadata::clawdstrike("0.1.3").with_original_uid("uid-1");
let json = serde_json::to_string(&m).unwrap();
let m2: Metadata = serde_json::from_str(&json).unwrap();
assert_eq!(m, m2);
}
}