• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use super::{Console, UploadConfig, UploadOperator, Uploader};
15 use crate::async_impl::MultiPart;
16 use crate::AsyncRead;
17 
18 /// A builder that can create a `Uploader`.
19 ///
20 /// You can use this builder to build a `Uploader` step by step.
21 ///
22 /// # Examples
23 ///
24 /// ```
25 /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader};
26 ///
27 /// let uploader = UploaderBuilder::new()
28 ///     .reader("HelloWorld".as_bytes())
29 ///     .console()
30 ///     .build();
31 /// ```
32 pub struct UploaderBuilder<S> {
33     state: S,
34 }
35 
36 /// A state indicates that `UploaderBuilder` wants a `Reader`.
37 pub struct WantsReader;
38 
39 impl UploaderBuilder<WantsReader> {
40     /// Creates a `UploaderBuilder` in the `WantsReader` state.
41     ///
42     /// # Examples
43     ///
44     /// ```
45     /// # use ylong_http_client::async_impl::UploaderBuilder;
46     ///
47     /// let builder = UploaderBuilder::new();
48     /// ```
new() -> Self49     pub fn new() -> Self {
50         Self { state: WantsReader }
51     }
52 
53     /// Sets a reader that needs to be read.
54     ///
55     /// # Examples
56     ///
57     /// ```
58     /// # use ylong_http_client::async_impl::UploaderBuilder;
59     ///
60     /// let builder = UploaderBuilder::new().reader("HelloWorld".as_bytes());
61     /// ```
reader<R: AsyncRead>(self, reader: R) -> UploaderBuilder<WantsOperator<R>>62     pub fn reader<R: AsyncRead>(self, reader: R) -> UploaderBuilder<WantsOperator<R>> {
63         UploaderBuilder {
64             state: WantsOperator {
65                 reader,
66                 config: UploadConfig::default(),
67             },
68         }
69     }
70 
71     /// Sets a `multipart` that needs to be read. The size of the multipart will
72     /// be set automatically if it contains.
73     ///
74     /// # Examples
75     ///
76     /// ```
77     /// # use ylong_http_client::async_impl::UploaderBuilder;
78     ///
79     /// let builder = UploaderBuilder::new().reader("HelloWorld".as_bytes());
80     /// ```
multipart(self, reader: MultiPart) -> UploaderBuilder<WantsOperator<MultiPart>>81     pub fn multipart(self, reader: MultiPart) -> UploaderBuilder<WantsOperator<MultiPart>> {
82         let total_bytes = reader.total_bytes();
83         UploaderBuilder {
84             state: WantsOperator {
85                 reader,
86                 config: UploadConfig { total_bytes },
87             },
88         }
89     }
90 }
91 
92 impl Default for UploaderBuilder<WantsReader> {
default() -> Self93     fn default() -> Self {
94         Self::new()
95     }
96 }
97 
98 /// A state indicates that `UploaderBuilder` wants an `UploadOperator`.
99 pub struct WantsOperator<R> {
100     reader: R,
101     config: UploadConfig,
102 }
103 
104 impl<R: AsyncRead> UploaderBuilder<WantsOperator<R>> {
105     /// Sets a customized `UploaderOperator`.
106     ///
107     /// Then the `UploaderBuilder` will switch to `WantsConfig` state.
108     ///
109     /// # Examples
110     ///
111     /// ```
112     /// # use std::pin::Pin;
113     /// # use std::task::{Context, Poll};
114     /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader, UploadOperator};
115     /// # use ylong_http_client::{HttpClientError, Response};
116     ///
117     /// struct MyOperator;
118     ///
119     /// impl UploadOperator for MyOperator {
120     ///     fn poll_progress(
121     ///         self: Pin<&mut Self>,
122     ///         cx: &mut Context<'_>,
123     ///         uploaded: u64,
124     ///         total: Option<u64>,
125     ///     ) -> Poll<Result<(), HttpClientError>> {
126     ///         todo!()
127     ///     }
128     /// }
129     ///
130     /// let builder = UploaderBuilder::new()
131     ///     .reader("HelloWorld".as_bytes())
132     ///     .operator(MyOperator);
133     /// ```
operator<T: UploadOperator>(self, operator: T) -> UploaderBuilder<WantsConfig<R, T>>134     pub fn operator<T: UploadOperator>(self, operator: T) -> UploaderBuilder<WantsConfig<R, T>> {
135         UploaderBuilder {
136             state: WantsConfig {
137                 reader: self.state.reader,
138                 operator,
139                 config: self.state.config,
140             },
141         }
142     }
143 
144     /// Sets a `Console` to this `Uploader`. The download result and progress
145     /// will be displayed on the console.
146     ///
147     /// The `Console` needs a `Reader` to display.
148     ///
149     /// # Examples
150     ///
151     /// ```
152     /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader};
153     /// # use ylong_http_client::Response;
154     ///
155     /// let builder = UploaderBuilder::new()
156     ///     .reader("HelloWorld".as_bytes())
157     ///     .console();
158     /// ```
console(self) -> UploaderBuilder<WantsConfig<R, Console>>159     pub fn console(self) -> UploaderBuilder<WantsConfig<R, Console>> {
160         UploaderBuilder {
161             state: WantsConfig {
162                 reader: self.state.reader,
163                 operator: Console,
164                 config: self.state.config,
165             },
166         }
167     }
168 }
169 
170 /// A state indicates that `UploaderBuilder` wants some configurations.
171 pub struct WantsConfig<R, T> {
172     reader: R,
173     operator: T,
174     config: UploadConfig,
175 }
176 
177 impl<R, T> UploaderBuilder<WantsConfig<R, T>> {
178     /// Sets the total bytes of the uploaded content.
179     ///
180     /// Default is `None` which means that you don't know the size of the
181     /// content.
182     ///
183     /// # Examples
184     ///
185     /// ```
186     /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader};
187     ///
188     /// let builder = UploaderBuilder::new()
189     ///     .reader("HelloWorld".as_bytes())
190     ///     .console()
191     ///     .total_bytes(Some(10));
192     /// ```
total_bytes(mut self, total_bytes: Option<u64>) -> Self193     pub fn total_bytes(mut self, total_bytes: Option<u64>) -> Self {
194         self.state.config.total_bytes = total_bytes;
195         self
196     }
197 
198     /// Returns a `Uploader` that uses this `UploaderBuilder` configuration.
199     ///
200     /// # Examples
201     ///
202     /// ```
203     /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader};
204     /// # use ylong_http_client::Response;
205     ///
206     /// let uploader = UploaderBuilder::new()
207     ///     .reader("HelloWorld".as_bytes())
208     ///     .console()
209     ///     .build();
210     /// ```
build(self) -> Uploader<R, T>211     pub fn build(self) -> Uploader<R, T> {
212         Uploader {
213             reader: self.state.reader,
214             operator: self.state.operator,
215             config: self.state.config,
216             info: None,
217         }
218     }
219 }
220