use std::{ops::Index, slice};
use advisory::Advisory;
use db::AdvisoryDatabase;
use lockfile::Lockfile;
use package::Package;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Vulnerabilities(Vec<Vulnerability>);
impl Vulnerabilities {
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)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> Iter {
Iter(self.0.as_slice().iter())
}
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
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Vulnerability {
pub advisory: Advisory,
pub package: Package,
}
impl Vulnerability {
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()
}
}
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()
}
}