use std::collections::hash_map::HashMap;
use std::fmt;
use std::task::Poll;
use crate::core::package::PackageSet;
use crate::core::SourceId;
use crate::core::{Dependency, Package, PackageId};
use crate::sources::IndexSummary;
use crate::util::{CargoResult, Config};
pub trait Source {
fn source_id(&self) -> SourceId;
fn replaced_source_id(&self) -> SourceId {
self.source_id()
}
fn supports_checksums(&self) -> bool;
fn requires_precise(&self) -> bool;
fn query(
&mut self,
dep: &Dependency,
kind: QueryKind,
f: &mut dyn FnMut(IndexSummary),
) -> Poll<CargoResult<()>>;
fn query_vec(
&mut self,
dep: &Dependency,
kind: QueryKind,
) -> Poll<CargoResult<Vec<IndexSummary>>> {
let mut ret = Vec::new();
self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret)
}
fn invalidate_cache(&mut self);
fn set_quiet(&mut self, quiet: bool);
fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
fn download_now(self: Box<Self>, package: PackageId, config: &Config) -> CargoResult<Package>
where
Self: std::marker::Sized,
{
let mut sources = SourceMap::new();
sources.insert(self);
let pkg_set = PackageSet::new(&[package], sources, config)?;
let pkg = pkg_set.get_one(package)?;
Ok(Package::clone(pkg))
}
fn finish_download(&mut self, pkg_id: PackageId, contents: Vec<u8>) -> CargoResult<Package>;
fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
fn verify(&self, _pkg: PackageId) -> CargoResult<()> {
Ok(())
}
fn describe(&self) -> String;
fn is_replaced(&self) -> bool {
false
}
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]);
fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>>;
fn block_until_ready(&mut self) -> CargoResult<()>;
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum QueryKind {
Exact,
Fuzzy,
}
pub enum MaybePackage {
Ready(Package),
Download {
url: String,
descriptor: String,
authorization: Option<String>,
},
}
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
fn source_id(&self) -> SourceId {
(**self).source_id()
}
fn replaced_source_id(&self) -> SourceId {
(**self).replaced_source_id()
}
fn supports_checksums(&self) -> bool {
(**self).supports_checksums()
}
fn requires_precise(&self) -> bool {
(**self).requires_precise()
}
fn query(
&mut self,
dep: &Dependency,
kind: QueryKind,
f: &mut dyn FnMut(IndexSummary),
) -> Poll<CargoResult<()>> {
(**self).query(dep, kind, f)
}
fn invalidate_cache(&mut self) {
(**self).invalidate_cache()
}
fn set_quiet(&mut self, quiet: bool) {
(**self).set_quiet(quiet)
}
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
(**self).download(id)
}
fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
(**self).finish_download(id, data)
}
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
(**self).fingerprint(pkg)
}
fn verify(&self, pkg: PackageId) -> CargoResult<()> {
(**self).verify(pkg)
}
fn describe(&self) -> String {
(**self).describe()
}
fn is_replaced(&self) -> bool {
(**self).is_replaced()
}
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
(**self).add_to_yanked_whitelist(pkgs);
}
fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {
(**self).is_yanked(pkg)
}
fn block_until_ready(&mut self) -> CargoResult<()> {
(**self).block_until_ready()
}
}
impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
fn source_id(&self) -> SourceId {
(**self).source_id()
}
fn replaced_source_id(&self) -> SourceId {
(**self).replaced_source_id()
}
fn supports_checksums(&self) -> bool {
(**self).supports_checksums()
}
fn requires_precise(&self) -> bool {
(**self).requires_precise()
}
fn query(
&mut self,
dep: &Dependency,
kind: QueryKind,
f: &mut dyn FnMut(IndexSummary),
) -> Poll<CargoResult<()>> {
(**self).query(dep, kind, f)
}
fn invalidate_cache(&mut self) {
(**self).invalidate_cache()
}
fn set_quiet(&mut self, quiet: bool) {
(**self).set_quiet(quiet)
}
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
(**self).download(id)
}
fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
(**self).finish_download(id, data)
}
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
(**self).fingerprint(pkg)
}
fn verify(&self, pkg: PackageId) -> CargoResult<()> {
(**self).verify(pkg)
}
fn describe(&self) -> String {
(**self).describe()
}
fn is_replaced(&self) -> bool {
(**self).is_replaced()
}
fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
(**self).add_to_yanked_whitelist(pkgs);
}
fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {
(**self).is_yanked(pkg)
}
fn block_until_ready(&mut self) -> CargoResult<()> {
(**self).block_until_ready()
}
}
#[derive(Default)]
pub struct SourceMap<'src> {
map: HashMap<SourceId, Box<dyn Source + 'src>>,
}
impl<'src> fmt::Debug for SourceMap<'src> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SourceMap ")?;
f.debug_set().entries(self.map.keys()).finish()
}
}
impl<'src> SourceMap<'src> {
pub fn new() -> SourceMap<'src> {
SourceMap {
map: HashMap::new(),
}
}
pub fn get(&self, id: SourceId) -> Option<&(dyn Source + 'src)> {
self.map.get(&id).map(|s| s.as_ref())
}
pub fn get_mut(&mut self, id: SourceId) -> Option<&mut (dyn Source + 'src)> {
self.map.get_mut(&id).map(|s| s.as_mut())
}
pub fn insert(&mut self, source: Box<dyn Source + 'src>) {
let id = source.source_id();
self.map.insert(id, source);
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn sources_mut<'a>(
&'a mut self,
) -> impl Iterator<Item = (&'a SourceId, &'a mut (dyn Source + 'src))> {
self.map.iter_mut().map(|(a, b)| (a, &mut **b))
}
pub fn add_source_map(&mut self, other: SourceMap<'src>) {
for (key, value) in other.map {
self.map.entry(key).or_insert(value);
}
}
}