[go: up one dir, main page]

cvss/
severity.rs

1//! Qualitative Severity Rating Scale
2
3use crate::{Error, Result};
4use alloc::borrow::ToOwned;
5use core::{fmt, str::FromStr};
6
7#[cfg(feature = "serde")]
8use {
9    alloc::string::String,
10    serde::{Deserialize, Serialize, de, ser},
11};
12
13/// Qualitative Severity Rating Scale
14///
15/// Described in CVSS v3.1 Specification: Section 5:
16/// <https://www.first.org/cvss/v3.1/specification-document#Qualitative-Severity-Rating-Scale>
17///
18/// And in CVSS v4.0 Specification: Section 6:
19/// <https://www.first.org/cvss/v4.0/specification-document#Qualitative-Severity-Rating-Scale>
20///
21/// The rating scales in v3 and v4 are the same.
22///
23/// > For some purposes it is useful to have a textual representation of the
24/// > scores.
25#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
26pub enum Severity {
27    /// None: CVSS Score 0.0
28    None,
29
30    /// Low: CVSS Score 0.1 - 3.9
31    Low,
32
33    /// Medium: CVSS Score 4.0 - 6.9
34    Medium,
35
36    /// High: CVSS Score 7.0 - 8.9
37    High,
38
39    /// Critical: CVSS Score 9.0 - 10.0
40    Critical,
41}
42
43impl Severity {
44    /// Get a `str` describing the severity level
45    pub fn as_str(self) -> &'static str {
46        match self {
47            Severity::None => "none",
48            Severity::Low => "low",
49            Severity::Medium => "medium",
50            Severity::High => "high",
51            Severity::Critical => "critical",
52        }
53    }
54}
55
56impl FromStr for Severity {
57    type Err = Error;
58
59    fn from_str(s: &str) -> Result<Self> {
60        match s.to_ascii_lowercase().as_str() {
61            "none" => Ok(Severity::None),
62            "low" => Ok(Severity::Low),
63            "medium" => Ok(Severity::Medium),
64            "high" => Ok(Severity::High),
65            "critical" => Ok(Severity::Critical),
66            _ => Err(Error::InvalidSeverity { name: s.to_owned() }),
67        }
68    }
69}
70
71impl fmt::Display for Severity {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        f.write_str(self.as_str())
74    }
75}
76
77#[cfg(feature = "serde")]
78#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
79impl<'de> Deserialize<'de> for Severity {
80    fn deserialize<D: de::Deserializer<'de>>(
81        deserializer: D,
82    ) -> core::result::Result<Self, D::Error> {
83        String::deserialize(deserializer)?
84            .parse()
85            .map_err(de::Error::custom)
86    }
87}
88
89#[cfg(feature = "serde")]
90#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
91impl Serialize for Severity {
92    fn serialize<S: ser::Serializer>(
93        &self,
94        serializer: S,
95    ) -> core::result::Result<S::Ok, S::Error> {
96        self.as_str().serialize(serializer)
97    }
98}