use crate::client::header::header_meta;
use crate::path::Path;
use crate::{Error, GetOptions, GetResult, ObjectMeta};
use crate::{GetResultPayload, Result};
use async_trait::async_trait;
use futures::{StreamExt, TryStreamExt};
use reqwest::Response;
#[async_trait]
pub trait GetClient: Send + Sync + 'static {
const STORE: &'static str;
async fn get_request(
&self,
path: &Path,
options: GetOptions,
head: bool,
) -> Result<Response>;
}
#[async_trait]
pub trait GetClientExt {
async fn get_opts(&self, location: &Path, options: GetOptions) -> Result<GetResult>;
async fn head(&self, location: &Path) -> Result<ObjectMeta>;
}
#[async_trait]
impl<T: GetClient> GetClientExt for T {
async fn get_opts(&self, location: &Path, options: GetOptions) -> Result<GetResult> {
let range = options.range.clone();
let response = self.get_request(location, options, false).await?;
let meta =
header_meta(location, response.headers()).map_err(|e| Error::Generic {
store: T::STORE,
source: Box::new(e),
})?;
let stream = response
.bytes_stream()
.map_err(|source| Error::Generic {
store: T::STORE,
source: Box::new(source),
})
.boxed();
Ok(GetResult {
range: range.unwrap_or(0..meta.size),
payload: GetResultPayload::Stream(stream),
meta,
})
}
async fn head(&self, location: &Path) -> Result<ObjectMeta> {
let options = GetOptions::default();
let response = self.get_request(location, options, true).await?;
header_meta(location, response.headers()).map_err(|e| Error::Generic {
store: T::STORE,
source: Box::new(e),
})
}
}