use std::fmt;
use std::sync::Arc;
use crate::cancellation::CancellationToken;
use crate::config::DownloadOptions;
use crate::error::{Error, Result};
use crate::event::ProgressEvent;
use crate::manifest::StreamSelector;
use crate::session::DownloadSession;
#[derive(Clone, Debug, Default)]
pub struct DownloadClient;
impl DownloadClient {
pub fn new() -> Self {
Self
}
pub fn prepare(&self, request: DownloadRequest) -> Result<DownloadSession> {
if request.input.trim().is_empty() {
return Err(Error::config("input must not be empty"));
}
Ok(DownloadSession::new(request))
}
}
type ProgressCallbackFn = dyn Fn(&ProgressEvent) -> Result<()> + Send + Sync + 'static;
#[derive(Clone)]
pub struct ProgressCallback {
callback: Arc<ProgressCallbackFn>,
}
impl ProgressCallback {
pub fn new<F>(callback: F) -> Self
where
F: Fn(&ProgressEvent) -> Result<()> + Send + Sync + 'static,
{
Self {
callback: Arc::new(callback),
}
}
pub fn emit(&self, event: &ProgressEvent) -> Result<()> {
(self.callback)(event)
}
}
impl fmt::Debug for ProgressCallback {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("ProgressCallback")
}
}
#[derive(Clone, Debug)]
pub struct DownloadRequest {
pub input: String,
pub options: DownloadOptions,
pub stream_selector: StreamSelector,
pub cancellation_token: CancellationToken,
pub progress_callback: Option<ProgressCallback>,
}
impl DownloadRequest {
pub fn new(input: impl Into<String>) -> Self {
Self {
input: input.into(),
options: DownloadOptions::default(),
stream_selector: StreamSelector::default(),
cancellation_token: CancellationToken::new(),
progress_callback: None,
}
}
pub fn with_options(mut self, options: DownloadOptions) -> Self {
self.options = options;
self
}
pub fn with_stream_selector(mut self, stream_selector: StreamSelector) -> Self {
self.stream_selector = stream_selector;
self
}
pub fn with_cancellation_token(mut self, cancellation_token: CancellationToken) -> Self {
self.cancellation_token = cancellation_token;
self
}
pub fn with_progress_callback(mut self, progress_callback: ProgressCallback) -> Self {
self.progress_callback = Some(progress_callback);
self
}
}
#[derive(Clone, Debug)]
pub struct LiveRecorder {
request: DownloadRequest,
}
impl LiveRecorder {
pub fn new(request: DownloadRequest) -> Self {
Self { request }
}
pub fn request(&self) -> &DownloadRequest {
&self.request
}
pub async fn start(self) -> Result<Vec<ProgressEvent>> {
Box::pin(DownloadClient::new().prepare(self.request)?.start()).await
}
}