use std::{collections::HashMap, fmt::Display, str::FromStr};
use purl::GenericPurl;
use crate::{Repository, supplychain::licenses::Licenses};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Dependency {
pub manager: String,
pub name: String,
pub namespace: Option<String>,
pub version: Option<String>,
path: Option<String>,
qualifiers: HashMap<String, String>,
pub licenses: Licenses,
repository: Option<Repository>,
purl: Option<GenericPurl<String>>,
}
impl Dependency {
pub fn new() -> Self {
Default::default()
}
pub fn purl(&self) -> String {
if let Some(purl) = &self.purl {
purl.to_string()
} else {
format!("pkg:{}@{}", self.manager, self.name)
}
}
}
impl Display for Dependency {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.purl())
}
}
impl From<&str> for Dependency {
fn from(value: &str) -> Self {
Dependency::from(GenericPurl::<String>::from_str(value).expect("Failed to parse PURL"))
}
}
impl From<String> for Dependency {
fn from(value: String) -> Self {
Dependency::from(value.as_str())
}
}
impl From<GenericPurl<String>> for Dependency {
fn from(value: GenericPurl<String>) -> Self {
Dependency {
name: value.name().to_string(),
namespace: value.namespace().map(|s| s.to_string()),
version: value.version().map(|s| s.to_string()),
manager: value.package_type().clone(),
purl: Some(value),
..Default::default()
}
}
}
impl From<(&str, &str)> for Dependency {
fn from(value: (&str, &str)) -> Self {
let mut dependency = Dependency::from(value.0);
dependency.licenses = Licenses::from(value.1);
dependency
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dependency_from_str() {
let dependency = Dependency::from("pkg:generic/namespace/name@version");
assert_eq!(dependency.name, "name");
assert_eq!(dependency.namespace, Some("namespace".to_string()));
assert_eq!(dependency.version, Some("version".to_string()));
assert_eq!(dependency.manager, "generic".to_string());
assert_eq!(
dependency.purl(),
"pkg:generic/namespace/name@version".to_string()
);
}
}