rustsec 0.7.0-alpha3

Client library for the RustSec security advisory database
Documentation
//! Vulnerabilities are an `Advisory` collection constructed by matching crates
//! in a particular `Lockfile` against all advisories in an `AdvisoryDatabase`
//! and looking for vulnerable versions.

use std::{ops::Index, slice};

use advisory::Advisory;
use db::AdvisoryDatabase;
use lockfile::Lockfile;
use package::Package;

/// A collection of vulnerabilities (i.e. matching advisories) for a given `Lockfile`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Vulnerabilities(Vec<Vulnerability>);

impl Vulnerabilities {
    /// Find all vulnerabilities for a given `AdvisoryDatabase` and `Lockfile`
    pub fn find(db: &AdvisoryDatabase, lockfile: &Lockfile) -> Self {
        let mut vulns = vec![];

        for package in &lockfile.packages {
            for advisory in db.advisories_for_crate(&package.name, &package.version) {
                vulns.push(Vulnerability::new(advisory, package))
            }
        }

        Vulnerabilities(vulns)
    }

    /// Number of vulnerabilities
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Are we blissfully vulnerability-free?
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Iterate over the vulnerabilities in this collection
    pub fn iter(&self) -> Iter {
        Iter(self.0.as_slice().iter())
    }

    /// Convert this collection into a vector
    pub fn into_vec(self) -> Vec<Vulnerability> {
        self.into()
    }
}

impl Index<usize> for Vulnerabilities {
    type Output = Vulnerability;

    fn index(&self, index: usize) -> &Vulnerability {
        &self.0[index]
    }
}

impl Into<Vec<Vulnerability>> for Vulnerabilities {
    fn into(self) -> Vec<Vulnerability> {
        self.0
    }
}

/// A vulnerable package and the associated advisory
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Vulnerability {
    /// A security advisory for which the package is vulnerable
    pub advisory: Advisory,

    /// A vulnerable package
    pub package: Package,
}

impl Vulnerability {
    /// Create a new vulnerability object from the given references
    pub fn new(advisory: &Advisory, package: &Package) -> Self {
        Self {
            advisory: advisory.clone(),
            package: package.clone(),
        }
    }
}

impl<'a> IntoIterator for &'a Vulnerabilities {
    type Item = &'a Vulnerability;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// Iterator over the advisory database
pub struct Iter<'a>(slice::Iter<'a, Vulnerability>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Vulnerability;

    fn next(&mut self) -> Option<&'a Vulnerability> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {
    fn len(&self) -> usize {
        self.0.len()
    }
}