aws_multipart_upload/client/
sdk.rs

1use crate::client::part::{CompletedPart, EntityTag};
2use crate::client::request::*;
3use crate::client::{DefaultRequestBuilder, RequestBuilder, SendRequest, UploadData, UploadId};
4use crate::error::{ErrorRepr, Result, UploadContext as _};
5
6use aws_config::ConfigLoader;
7
8/// AWS S3 SDK client.
9///
10/// Pairs a [`Client`] with a [`RequestBuilder`] used to set additional
11/// properties on request objects before sending.
12///
13/// [`Client`]: aws_sdk::Client
14/// [`RequestBuilder`]: super::request::RequestBuilder
15#[derive(Debug, Clone)]
16pub struct SdkClient<B = DefaultRequestBuilder>(aws_sdk::Client, B);
17
18impl SdkClient {
19    /// Create a new `SdkClient` with default [`RequestBuilder`].
20    ///
21    /// [`RequestBuilder`]: super::request::RequestBuilder
22    pub fn new(client: aws_sdk::Client) -> Self {
23        SdkClient(client, DefaultRequestBuilder)
24    }
25
26    /// Create a new `SdkClient` from the supplied [`ConfigLoader`].
27    ///
28    /// [`ConfigLoader`]: aws_config::ConfigLoader
29    pub async fn from_config(loader: ConfigLoader) -> Self {
30        let config = loader.load().await;
31        let client = aws_sdk::Client::new(&config);
32        Self::new(client)
33    }
34
35    /// Create a new `SdkClient` with default [`RequestBuilder`] using the
36    /// default [`ConfigLoader`].
37    pub async fn defaults() -> Self {
38        let loader = aws_config::from_env();
39        Self::from_config(loader).await
40    }
41
42    /// Set a request builder for this S3 client.
43    pub fn request_builder<B: RequestBuilder>(self, builder: B) -> SdkClient<B> {
44        SdkClient(self.0, builder)
45    }
46}
47
48impl<B: RequestBuilder> SdkClient<B> {
49    /// Create a default `CreateRequestBuilder` to set properties on for a
50    /// `CreateMultipartUpload` request.
51    pub(crate) fn new_create_builder(&self) -> CreateRequestBuilder {
52        self.0.create_multipart_upload()
53    }
54
55    /// Create a default `UploadPartRequestBuilder` to set properties on for an
56    /// `UploadPart`.
57    pub(crate) fn new_part_builder(&self) -> UploadPartRequestBuilder {
58        self.0.upload_part()
59    }
60
61    /// Create a default `CompleteRequestBuilder` to set properties on for a
62    /// `CompleteMultipartUpload` request.
63    pub(crate) fn new_complete_builder(&self) -> CompleteRequestBuilder {
64        self.0.complete_multipart_upload()
65    }
66
67    /// Create a default `CompleteRequestBuilder` to set properties on for a
68    /// `CompleteMultipartUpload` request.
69    pub(crate) fn new_abort_builder(&self) -> AbortRequestBuilder {
70        self.0.abort_multipart_upload()
71    }
72}
73
74impl<B: RequestBuilder> SendRequest for SdkClient<B> {
75    async fn send_create_upload_request(&self, req: CreateRequest) -> Result<UploadData> {
76        req.validate()?;
77        let base = self.new_create_builder();
78        let builder = req.with_builder(base);
79        let request = self.1.with_create_builder(builder);
80
81        let uri = req.uri();
82        let id = request
83            .send()
84            .await
85            .map_err(ErrorRepr::from)
86            .and_then(|resp| UploadId::try_from_create_resp(&resp))?;
87
88        Ok(UploadData::new(id, uri.clone()))
89    }
90
91    async fn send_new_part_upload_request(
92        &self,
93        mut req: UploadPartRequest,
94    ) -> Result<CompletedPart> {
95        req.validate()?;
96        let part_size = req.body.size();
97
98        let base = self.new_part_builder();
99        let builder = req.with_builder(base);
100        let request = self.1.with_upload_part_builder(builder);
101
102        let id = req.id();
103        let uri = req.uri();
104        let part = req.part_number();
105        let etag = request
106            .send()
107            .await
108            .map_err(ErrorRepr::from)
109            .and_then(|resp| EntityTag::try_from_upload_resp(&resp))
110            .upload_ctx(id, uri, part)?;
111
112        Ok(CompletedPart::new(id.clone(), etag, part, part_size))
113    }
114
115    async fn send_complete_upload_request(&self, req: CompleteRequest) -> Result<CompletedUpload> {
116        req.validate()?;
117        let base = self.new_complete_builder();
118        let builder = req.with_builder(base);
119        let request = self.1.with_complete_builder(builder);
120
121        let id = req.id();
122        let uri = req.uri();
123        let part = req.completed_parts.max_part_number();
124        let etag = request
125            .send()
126            .await
127            .map_err(ErrorRepr::from)
128            .and_then(|resp| EntityTag::try_from_complete_resp(&resp))
129            .upload_ctx(id, uri, part)?;
130
131        Ok(CompletedUpload::new(uri.clone(), etag))
132    }
133
134    async fn send_abort_upload_request(&self, req: AbortRequest) -> Result<()> {
135        let base = self.new_abort_builder();
136        let builder = req.with_builder(base);
137        let request = self.1.with_abort_builder(builder);
138        let _ = request.send().await.map_err(ErrorRepr::from)?;
139        Ok(())
140    }
141}