mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-24 22:30:03 +00:00
Optimize Download::and_visit_tar
: Use trait object to avoid monomorphization (#644)
by removing method `TarEntriesVisitor::finish` and associated type `TarEntriesVisitor::Target`. Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
parent
1ab979cde8
commit
959b465d81
4 changed files with 30 additions and 37 deletions
|
@ -101,11 +101,11 @@ impl Download {
|
||||||
/// NOTE that this API does not support gnu extension sparse file unlike
|
/// NOTE that this API does not support gnu extension sparse file unlike
|
||||||
/// [`Download::and_extract`].
|
/// [`Download::and_extract`].
|
||||||
#[instrument(skip(visitor))]
|
#[instrument(skip(visitor))]
|
||||||
pub async fn and_visit_tar<V: TarEntriesVisitor + Debug + Send + 'static>(
|
pub async fn and_visit_tar(
|
||||||
self,
|
self,
|
||||||
fmt: TarBasedFmt,
|
fmt: TarBasedFmt,
|
||||||
visitor: V,
|
visitor: &mut dyn TarEntriesVisitor,
|
||||||
) -> Result<V::Target, DownloadError> {
|
) -> Result<(), DownloadError> {
|
||||||
let stream = self
|
let stream = self
|
||||||
.client
|
.client
|
||||||
.get_stream(self.url)
|
.get_stream(self.url)
|
||||||
|
@ -114,11 +114,11 @@ impl Download {
|
||||||
|
|
||||||
debug!("Downloading and extracting then in-memory processing");
|
debug!("Downloading and extracting then in-memory processing");
|
||||||
|
|
||||||
let ret = extract_tar_based_stream_and_visit(stream, fmt, visitor).await?;
|
extract_tar_based_stream_and_visit(stream, fmt, visitor).await?;
|
||||||
|
|
||||||
debug!("Download, extraction and in-memory procession OK");
|
debug!("Download, extraction and in-memory procession OK");
|
||||||
|
|
||||||
Ok(ret)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download a file from the provided URL and extract it to the provided path.
|
/// Download a file from the provided URL and extract it to the provided path.
|
||||||
|
|
|
@ -84,21 +84,17 @@ pub enum TarEntryType {
|
||||||
/// Entires can be in arbitary order.
|
/// Entires can be in arbitary order.
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait TarEntriesVisitor: Send + Sync {
|
pub trait TarEntriesVisitor: Send + Sync {
|
||||||
type Target;
|
|
||||||
|
|
||||||
/// Will be called once per entry
|
/// Will be called once per entry
|
||||||
async fn visit(&mut self, entry: &mut dyn TarEntry) -> Result<(), DownloadError>;
|
async fn visit(&mut self, entry: &mut dyn TarEntry) -> Result<(), DownloadError>;
|
||||||
fn finish(self) -> Result<Self::Target, DownloadError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn extract_tar_based_stream_and_visit<S, V>(
|
pub(crate) async fn extract_tar_based_stream_and_visit<S>(
|
||||||
stream: S,
|
stream: S,
|
||||||
fmt: TarBasedFmt,
|
fmt: TarBasedFmt,
|
||||||
mut visitor: V,
|
visitor: &mut dyn TarEntriesVisitor,
|
||||||
) -> Result<V::Target, DownloadError>
|
) -> Result<(), DownloadError>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, DownloadError>> + Send + Sync,
|
S: Stream<Item = Result<Bytes, DownloadError>> + Send + Sync,
|
||||||
V: TarEntriesVisitor,
|
|
||||||
{
|
{
|
||||||
debug!("Extracting from {fmt} archive to process it in memory");
|
debug!("Extracting from {fmt} archive to process it in memory");
|
||||||
|
|
||||||
|
@ -125,5 +121,5 @@ where
|
||||||
copy(&mut entry, &mut sink).await?;
|
copy(&mut entry, &mut sink).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.finish()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,11 @@ pub async fn fetch_crate_cratesio(
|
||||||
|
|
||||||
let manifest_dir_path: PathBuf = format!("{name}-{version_name}").into();
|
let manifest_dir_path: PathBuf = format!("{name}-{version_name}").into();
|
||||||
|
|
||||||
Ok(Download::new(client, Url::parse(&crate_url)?)
|
let mut manifest_visitor = ManifestVisitor::new(manifest_dir_path);
|
||||||
.and_visit_tar(TarBasedFmt::Tgz, ManifestVisitor::new(manifest_dir_path))
|
|
||||||
.await?)
|
Download::new(client, Url::parse(&crate_url)?)
|
||||||
|
.and_visit_tar(TarBasedFmt::Tgz, &mut manifest_visitor)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
manifest_visitor.load_manifest()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
use std::{
|
use std::path::{Path, PathBuf};
|
||||||
io,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use cargo_toml::{Manifest, Value};
|
use cargo_toml::{Manifest, Value};
|
||||||
use normalize_path::NormalizePath;
|
use normalize_path::NormalizePath;
|
||||||
|
@ -37,8 +34,6 @@ impl ManifestVisitor {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl TarEntriesVisitor for ManifestVisitor {
|
impl TarEntriesVisitor for ManifestVisitor {
|
||||||
type Target = Manifest<Meta>;
|
|
||||||
|
|
||||||
async fn visit(&mut self, entry: &mut dyn TarEntry) -> Result<(), DownloadError> {
|
async fn visit(&mut self, entry: &mut dyn TarEntry) -> Result<(), DownloadError> {
|
||||||
let path = entry.path()?;
|
let path = entry.path()?;
|
||||||
let path = path.normalize();
|
let path = path.normalize();
|
||||||
|
@ -70,22 +65,20 @@ impl TarEntriesVisitor for ManifestVisitor {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ManifestVisitor {
|
||||||
/// Load binstall metadata using the extracted information stored in memory.
|
/// Load binstall metadata using the extracted information stored in memory.
|
||||||
fn finish(self) -> Result<Self::Target, DownloadError> {
|
pub(super) fn load_manifest(self) -> Result<Manifest<Meta>, BinstallError> {
|
||||||
Ok(load_manifest(&self.cargo_toml_content, &self.vfs).map_err(io::Error::from)?)
|
debug!("Loading manifest directly from extracted file");
|
||||||
|
|
||||||
|
// Load and parse manifest
|
||||||
|
let mut manifest = Manifest::from_slice_with_metadata(&self.cargo_toml_content)?;
|
||||||
|
|
||||||
|
// Checks vfs for binary output names
|
||||||
|
manifest.complete_from_abstract_filesystem::<Value, _>(&self.vfs, None)?;
|
||||||
|
|
||||||
|
// Return metadata
|
||||||
|
Ok(manifest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_manifest(slice: &[u8], vfs: &Vfs) -> Result<Manifest<Meta>, BinstallError> {
|
|
||||||
debug!("Loading manifest directly from extracted file");
|
|
||||||
|
|
||||||
// Load and parse manifest
|
|
||||||
let mut manifest = Manifest::from_slice_with_metadata(slice)?;
|
|
||||||
|
|
||||||
// Checks vfs for binary output names
|
|
||||||
manifest.complete_from_abstract_filesystem::<Value, _>(vfs, None)?;
|
|
||||||
|
|
||||||
// Return metadata
|
|
||||||
Ok(manifest)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue