nvd_cvss/v4/
exploit_maturity.rs1use crate::error::{CVSSError, Result};
2use crate::metric::{Help, Metric, MetricType, MetricTypeV4, Worth};
3use serde::{Deserialize, Serialize};
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
8#[serde(rename_all = "UPPERCASE")]
9pub enum ExploitMaturity {
10 NotDefined,
12 Attacked,
14 Poc,
16 Unreported,
18}
19
20impl Default for ExploitMaturity {
21 fn default() -> Self {
22 Self::Attacked
24 }
25}
26impl ExploitMaturity {
27 pub(crate) fn eq5(&self) -> Option<u32> {
31 match self {
32 Self::NotDefined => None,
33 Self::Attacked => Some(0),
34 Self::Poc => Some(1),
35 Self::Unreported => Some(2),
36 }
37 }
38}
39
40impl FromStr for ExploitMaturity {
41 type Err = CVSSError;
42
43 fn from_str(s: &str) -> Result<Self> {
44 let name = Self::name();
45 let s = s.to_uppercase();
46 let (_name, v) = s
47 .split_once(&format!("{}:", name))
48 .ok_or(CVSSError::InvalidCVSS {
49 key: name.to_string(),
50 value: s.to_string(),
51 expected: name.to_string(),
52 })?;
53 let c = v.chars().next();
54 match c {
55 Some('A') => Ok(Self::Attacked),
56 Some('P') => Ok(Self::Poc),
57 Some('U') => Ok(Self::Unreported),
58 Some('X') => Ok(Self::NotDefined),
59 _ => Err(CVSSError::InvalidCVSS {
60 key: name.to_string(),
61 value: format!("{:?}", c),
62 expected: "A,P,U,X".to_string(),
63 }),
64 }
65 }
66}
67
68impl Display for ExploitMaturity {
69 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{}:{}", Self::name(), self.as_str())
71 }
72}
73
74impl Metric for ExploitMaturity {
75 const TYPE: MetricType = MetricType::V4(MetricTypeV4::E);
76
77 fn help(&self) -> Help {
78 match self {
79 Self::NotDefined => Help {
80 worth: Worth::Worst,
81 des: "".to_string(),
82 },
83 Self::Attacked => Help {
84 worth: Worth::Worst,
85 des: "".to_string(),
86 },
87 Self::Poc => Help {
88 worth: Worth::Worst,
89 des: "".to_string(),
90 },
91 Self::Unreported => Help {
92 worth: Worth::Worst,
93 des: "".to_string(),
94 },
95 }
96 }
97
98 fn score(&self) -> f32 {
99 match self {
100 Self::NotDefined => 0.0,
101 Self::Attacked => 0.0,
102 Self::Poc => 0.1,
103 Self::Unreported => 0.2,
104 }
105 }
106
107 fn as_str(&self) -> &'static str {
108 match self {
109 Self::NotDefined => "X",
110 Self::Attacked => "A",
111 Self::Poc => "P",
112 Self::Unreported => "N",
113 }
114 }
115}