use std::{cell::RefCell, rc::Rc};
use cargo_metadata::{CargoOpt, Metadata};
use once_cell::unsync::OnceCell;
use crate::{
advisory::AdvisoryClient, crates_io::CratesIoClient, geiger::GeigerClient,
repo::github::GitHubClient, ManifestPath,
};
use super::IndicateAdapter;
pub struct IndicateAdapterBuilder {
manifest_path: ManifestPath,
features: Vec<CargoOpt>,
metadata: Option<Metadata>,
github_client: Option<GitHubClient>,
advisory_client: Option<AdvisoryClient>,
geiger_client: Option<GeigerClient>,
crates_io_client: Option<CratesIoClient>,
}
impl IndicateAdapterBuilder {
#[must_use]
pub fn new(manifest_path: ManifestPath) -> IndicateAdapterBuilder {
Self {
manifest_path,
features: Vec::new(),
metadata: None,
github_client: None,
advisory_client: None,
geiger_client: None,
crates_io_client: None,
}
}
#[must_use]
pub fn build(self) -> IndicateAdapter {
assert!(
self.features.is_empty() || self.metadata.is_none(),
"features and metadata both set explicitly at the same time"
);
let metadata = match self.metadata {
Some(m) => m,
None => self
.manifest_path
.metadata(self.features.clone())
.unwrap_or_else(|e| {
panic!("could not generate metadata due to error: {e}")
}),
};
let advisory_client =
self.advisory_client.map_or_else(OnceCell::default, |ac| {
OnceCell::with_value(Rc::new(ac))
});
let geiger_client =
self.geiger_client.map_or_else(OnceCell::default, |gc| {
OnceCell::with_value(Rc::new(gc))
});
let crates_io_client =
self.crates_io_client.map_or_else(OnceCell::default, |c| {
OnceCell::with_value(Rc::new(RefCell::new(c)))
});
IndicateAdapter {
manifest_path: Rc::new(self.manifest_path),
features: self.features,
metadata: Rc::new(metadata),
packages: OnceCell::new(),
direct_dependencies: OnceCell::new(),
gh_client: Rc::new(RefCell::new(
self.github_client.unwrap_or_default(),
)),
advisory_client,
geiger_client,
crates_io_client,
}
}
#[must_use]
pub fn features(mut self, features: Vec<CargoOpt>) -> Self {
self.features = features;
self
}
#[must_use]
pub fn metadata(mut self, metadata: Metadata) -> Self {
self.metadata = Some(metadata);
self
}
#[must_use]
pub fn github_client(mut self, github_client: GitHubClient) -> Self {
self.github_client = Some(github_client);
self
}
#[must_use]
pub fn advisory_client(mut self, advisory_client: AdvisoryClient) -> Self {
self.advisory_client = Some(advisory_client);
self
}
#[must_use]
pub fn geiger_client(mut self, geiger_client: GeigerClient) -> Self {
self.geiger_client = Some(geiger_client);
self
}
#[must_use]
pub fn crates_io_client(
mut self,
crates_io_client: CratesIoClient,
) -> Self {
self.crates_io_client = Some(crates_io_client);
self
}
}
impl From<IndicateAdapterBuilder> for IndicateAdapter {
fn from(value: IndicateAdapterBuilder) -> Self {
value.build()
}
}