use crate::{Error, Result};
use alloc::borrow::ToOwned;
use core::{
fmt::{self, Debug, Display},
str::FromStr,
};
pub trait Metric: Copy + Clone + Debug + Display + Eq + FromStr + Ord {
const TYPE: MetricType;
fn name() -> &'static str {
Self::TYPE.name()
}
fn score(self) -> f64;
fn as_str(self) -> &'static str;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum MetricType {
A,
AC,
AV,
C,
I,
PR,
S,
UI,
}
impl MetricType {
pub fn name(self) -> &'static str {
match self {
Self::A => "A",
Self::AC => "AC",
Self::AV => "AV",
Self::C => "C",
Self::I => "I",
Self::PR => "PR",
Self::S => "S",
Self::UI => "UI",
}
}
pub fn description(self) -> &'static str {
match self {
Self::A => "Availability Impact",
Self::AC => "Attack Complexity",
Self::AV => "Attack Vector",
Self::C => "Confidentiality Impact",
Self::I => "Integrity Impact",
Self::PR => "Privileges Required",
Self::S => "Scope",
Self::UI => "User Interaction",
}
}
}
impl Display for MetricType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
impl FromStr for MetricType {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"A" => Ok(Self::A),
"AC" => Ok(Self::AC),
"AV" => Ok(Self::AV),
"C" => Ok(Self::C),
"I" => Ok(Self::I),
"PR" => Ok(Self::PR),
"S" => Ok(Self::S),
"UI" => Ok(Self::UI),
_ => Err(Error::UnknownMetric { name: s.to_owned() }),
}
}
}