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] pub 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}