#![allow(unused_variables)]
use async_stream::stream;
use futures::StreamExt as _;
use std::sync::Arc;
use tokio::io::AsyncBufRead;
pub trait DownloadsReporter: Send + Sync {
type DownloadProgressReporter: DownloadProgressReporter + 'static;
fn report_download(self: Arc<Self>, name: String) -> Self::DownloadProgressReporter;
}
impl DownloadsReporter for () {
type DownloadProgressReporter = ();
fn report_download(self: Arc<Self>, name: String) -> Self::DownloadProgressReporter {}
}
pub trait DownloadProgressReporter: Send + Sync {
fn report_start(&self) {}
fn report_progress(&self, total: u64, len: u64) {}
fn report_done(&self) {}
}
impl DownloadProgressReporter for () {}
pub trait PatchesReporter: Send + Sync {
type PatchProgressReporter: PatchProgressReporter + 'static;
fn report_patch(self: Arc<Self>, name: String) -> Self::PatchProgressReporter;
}
impl PatchesReporter for () {
type PatchProgressReporter = ();
fn report_patch(self: Arc<Self>, name: String) -> Self::PatchProgressReporter {}
}
pub trait PatchProgressReporter: Send + Sync {
fn report_done(&self) {}
}
impl PatchProgressReporter for () {}
pub(crate) fn response_to_async_read<R: DownloadProgressReporter>(
response: reqwest::Response,
reporter: Arc<R>,
) -> impl AsyncBufRead {
let total_len = response.content_length().unwrap_or(0);
reporter.report_progress(total_len, 0);
let mut bytes_downloaded = 0;
let mut stream = response.bytes_stream();
let bytes = stream!({
while let Some(chunk) = stream.next().await {
let chunk = match chunk {
Ok(chunk) => chunk,
Err(err) => {
yield Err(std::io::Error::other(err));
continue;
}
};
bytes_downloaded += chunk.len() as u64;
reporter.report_progress(total_len, bytes_downloaded);
yield Ok(chunk);
}
reporter.report_done();
});
tokio_util::io::StreamReader::new(bytes)
}