cve/
lib.rs

1mod timestamp;
2
3pub use timestamp::*;
4
5pub mod common;
6pub mod published;
7pub mod rejected;
8
9use std::num::NonZeroUsize;
10
11#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
12#[serde(rename_all = "camelCase")]
13#[serde(untagged)]
14#[allow(clippy::large_enum_variant)]
15pub enum Cve {
16    #[serde(rename_all = "camelCase")]
17    Published(Published),
18    #[serde(rename_all = "camelCase")]
19    Rejected(Rejected),
20}
21
22impl Cve {
23    pub fn id(&self) -> &str {
24        &self.common_metadata().id
25    }
26
27    pub fn common_metadata(&self) -> &common::Metadata {
28        match self {
29            Self::Published(cve) => &cve.metadata.common,
30            Self::Rejected(cve) => &cve.metadata.common,
31        }
32    }
33}
34
35#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
36#[serde(rename_all = "camelCase")]
37pub struct Published {
38    pub data_type: DataType,
39    pub data_version: DataVersion,
40    #[serde(rename = "cveMetadata")]
41    pub metadata: published::Metadata,
42    pub containers: published::Containers,
43}
44
45#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
46#[serde(rename_all = "camelCase")]
47pub struct Rejected {
48    pub data_type: DataType,
49    pub data_version: DataVersion,
50    #[serde(rename = "cveMetadata")]
51    pub metadata: rejected::Metadata,
52    pub containers: rejected::Containers,
53}
54
55const fn default_serial() -> NonZeroUsize {
56    NonZeroUsize::new(1).unwrap()
57}
58
59fn is_default_serial(value: &NonZeroUsize) -> bool {
60    *value == default_serial()
61}
62
63#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
64#[serde(rename_all = "UPPERCASE")]
65#[non_exhaustive] // NOTE: once we reach 6.x, we need a breaking version
66pub enum DataVersion {
67    #[serde(rename = "5.0")]
68    V5_0,
69    #[serde(rename = "5.1")]
70    V5_1,
71    #[serde(rename = "5.2")]
72    V5_2,
73}
74
75#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
76#[serde(rename_all = "UPPERCASE")]
77pub enum DataType {
78    #[serde(rename = "CVE_RECORD")]
79    Record,
80}
81
82mod state {
83    use serde::de::*;
84    use std::fmt::Formatter;
85
86    pub struct ConstValue(pub &'static str);
87
88    impl Visitor<'_> for ConstValue {
89        type Value = ();
90
91        fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
92            write!(formatter, "Must have a string value of '{}'", self.0)
93        }
94
95        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
96        where
97            E: Error,
98        {
99            match v == self.0 {
100                true => Ok(()),
101                false => Err(E::custom(format!("Value must be: {} (was: {})", self.0, v))),
102            }
103        }
104    }
105}