1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#[derive(Debug, Clone, PartialEq, Ord, PartialOrd, Eq)]
pub enum CvssVersion {
    V2_0,
    V3_0,
    V3_1,
}

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct CvssVector {
    pub version: CvssVersion,
    pub vector: String,
}

/// A CVSS abstract
pub trait Cvss {
    /// The version of this cvss value
    fn version(&self) -> Option<CvssVersion>;

    /// The cvss vector of this cvss value
    fn vector(&self) -> Option<String>;

    /// The cvss vector of this cvss value
    fn as_vector(&self) -> Option<CvssVector> {
        self.version().zip(self.vector())
            .map(|(version, vector)| CvssVector {
                version,
                vector,
            })
    }
}

impl<T: Cvss> Cvss for &T {
    fn version(&self) -> Option<CvssVersion> {
        (*self).version()
    }
    fn vector(&self) -> Option<String> {
        (*self).vector()
    }
}

impl<T: Cvss + Sized> TryInto<CvssVector> for (T, ) {
    type Error = ();

    fn try_into(self) -> Result<CvssVector, Self::Error> {
        let version = self.0.version();
        let vector = self.0.vector();
        version.zip(vector)
            .map(|(version, vector)| {
                CvssVector {
                    version,
                    vector,
                }
            })
            .ok_or(())
    }
}