use aws_config::ConfigLoader;
use crate::client::part::{CompletedPart, EntityTag};
use crate::client::request::*;
use crate::client::{
DefaultRequestBuilder, RequestBuilder, UploadApi, UploadData, UploadId,
};
use crate::error::{ErrorRepr, ErrorWithUpload as _, Result};
#[derive(Debug, Clone)]
pub struct SdkClient<B = DefaultRequestBuilder>(aws_sdk::Client, B);
impl SdkClient {
pub fn new(client: aws_sdk::Client) -> Self {
SdkClient(client, DefaultRequestBuilder)
}
pub async fn from_config(loader: ConfigLoader) -> Self {
let config = loader.load().await;
let client = aws_sdk::Client::new(&config);
Self::new(client)
}
pub async fn defaults() -> Self {
let loader = aws_config::from_env();
Self::from_config(loader).await
}
pub fn with_request_builder<B: RequestBuilder>(
self,
builder: B,
) -> SdkClient<B> {
SdkClient(self.0, builder)
}
pub fn client_ref(&self) -> &aws_sdk::Client {
&self.0
}
}
impl<B: RequestBuilder> SdkClient<B> {
pub(crate) fn new_create_builder(&self) -> CreateRequestBuilder {
self.0.create_multipart_upload()
}
pub(crate) fn new_part_builder(&self) -> UploadPartRequestBuilder {
self.0.upload_part()
}
pub(crate) fn new_complete_builder(&self) -> CompleteRequestBuilder {
self.0.complete_multipart_upload()
}
pub(crate) fn new_abort_builder(&self) -> AbortRequestBuilder {
self.0.abort_multipart_upload()
}
}
impl<B: RequestBuilder> UploadApi for SdkClient<B> {
async fn send_create_upload_request(
&self,
req: CreateRequest,
) -> Result<UploadData> {
req.validate()?;
let base = self.new_create_builder();
let builder = req.with_builder(base);
let request = self.1.with_create_builder(builder);
let uri = req.uri();
let id = request
.send()
.await
.map_err(ErrorRepr::from)
.and_then(|resp| UploadId::try_from_create_resp(&resp))?;
Ok(UploadData::new(id, uri.clone()))
}
async fn send_new_part_upload_request(
&self,
mut req: UploadPartRequest,
) -> Result<CompletedPart> {
req.validate()?;
let part_size = req.body.size();
let base = self.new_part_builder();
let builder = req.with_builder(base);
let request = self.1.with_upload_part_builder(builder);
let part = req.part_number();
let etag = request
.send()
.await
.map_err(ErrorRepr::from)
.and_then(|resp| EntityTag::try_from_upload_resp(&resp))?;
Ok(CompletedPart::new(etag, part, part_size))
}
async fn send_complete_upload_request(
&self,
req: CompleteRequest,
) -> Result<CompletedUpload> {
req.validate()?;
let base = self.new_complete_builder();
let builder = req.with_builder(base);
let request = self.1.with_complete_builder(builder);
let id = req.id();
let uri = req.uri();
let completed = req.completed_parts();
let etag = request
.send()
.await
.map_err(ErrorRepr::from)
.and_then(|resp| EntityTag::try_from_complete_resp(&resp))
.err_with_upl(id, uri, completed)?;
Ok(CompletedUpload::new(uri.clone(), etag))
}
async fn send_abort_upload_request(&self, req: AbortRequest) -> Result<()> {
let base = self.new_abort_builder();
let builder = req.with_builder(base);
let request = self.1.with_abort_builder(builder);
let _ = request.send().await.map_err(ErrorRepr::from)?;
Ok(())
}
}