qiniu_objects_manager/bucket.rs
1use super::{
2 batch_operations::BatchOperations,
3 callbacks::Callbacks,
4 list::{ListIter, ListVersion},
5 mime::Mime,
6 operation::{
7 CopyObject, CopyObjectBuilder, DeleteObject, DeleteObjectBuilder, Entry, ModifyObjectLifeCycle,
8 ModifyObjectLifeCycleBuilder, ModifyObjectMetadata, ModifyObjectMetadataBuilder, ModifyObjectStatus,
9 ModifyObjectStatusBuilder, MoveObject, MoveObjectBuilder, SetObjectType, SetObjectTypeBuilder, StatObject,
10 StatObjectBuilder, UnfreezeObject, UnfreezeObjectBuilder,
11 },
12 ObjectsManager,
13};
14use anyhow::Result as AnyResult;
15use assert_impl::assert_impl;
16use once_cell::sync::OnceCell;
17use qiniu_apis::{
18 http::ResponseParts,
19 http_client::{BucketName, BucketRegionsProvider, RegionsProvider, RequestBuilderParts, ResponseError},
20 upload_token::FileType,
21};
22use std::{borrow::Cow, io::Result as IOResult, mem::take, sync::Arc};
23
24#[cfg(feature = "async")]
25use {super::list::ListStream, async_once_cell::OnceCell as AsyncOnceCell};
26
27/// 七牛存储空间管理器
28#[derive(Debug, Clone)]
29pub struct Bucket(Arc<BucketInner>);
30
31#[derive(Debug)]
32struct BucketInner {
33 name: BucketName,
34 objects_manager: ObjectsManager,
35 region_provider: Option<Box<dyn RegionsProvider>>,
36 bucket_regions_provider: OnceCell<BucketRegionsProvider>,
37
38 #[cfg(feature = "async")]
39 async_bucket_regions_provider: AsyncOnceCell<BucketRegionsProvider>,
40}
41
42impl Bucket {
43 pub(super) fn new(
44 name: BucketName,
45 objects_manager: ObjectsManager,
46 region_provider: Option<Box<dyn RegionsProvider>>,
47 ) -> Self {
48 Self(Arc::new(BucketInner {
49 name,
50 objects_manager,
51 region_provider,
52 bucket_regions_provider: Default::default(),
53
54 #[cfg(feature = "async")]
55 async_bucket_regions_provider: AsyncOnceCell::new(),
56 }))
57 }
58
59 /// 获取存储空间名称
60 #[inline]
61 pub fn name(&self) -> &BucketName {
62 &self.0.name
63 }
64
65 /// 获取对象管理器
66 #[inline]
67 pub fn objects_manager(&self) -> &ObjectsManager {
68 &self.0.objects_manager
69 }
70
71 /// 创建列举操作构建器
72 ///
73 /// ##### 阻塞代码示例
74 ///
75 /// ```
76 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
77 /// use futures::stream::TryStreamExt;
78 ///
79 /// # fn example() -> anyhow::Result<()> {
80 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
81 /// let object_manager = ObjectsManager::new(credential);
82 /// let bucket = object_manager.bucket("test-bucket");
83 /// let mut iter = bucket.list().iter();
84 /// while let Some(object) = iter.next() {
85 /// let object = object?;
86 /// println!("fsize: {:?}", object.get_size_as_u64());
87 /// println!("hash: {:?}", object.get_hash_as_str());
88 /// println!("mime_type: {:?}", object.get_mime_type_as_str());
89 /// }
90 /// # Ok(())
91 /// # }
92 /// ```
93 ///
94 /// ##### 异步代码示例
95 ///
96 /// ```
97 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
98 /// use futures::stream::TryStreamExt;
99 ///
100 /// # async fn example() -> anyhow::Result<()> {
101 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
102 /// let object_manager = ObjectsManager::new(credential);
103 /// let bucket = object_manager.bucket("test-bucket");
104 /// let mut stream = bucket.list().stream();
105 /// while let Some(object) = stream.try_next().await? {
106 /// println!("fsize: {:?}", object.get_size_as_u64());
107 /// println!("hash: {:?}", object.get_hash_as_str());
108 /// println!("mime_type: {:?}", object.get_mime_type_as_str());
109 /// }
110 /// # Ok(())
111 /// # }
112 /// ```
113 #[inline]
114 pub fn list(&self) -> ListBuilder<'_> {
115 ListBuilder::new(self)
116 }
117
118 /// 创建对象元信息获取操作构建器
119 ///
120 /// ##### 阻塞代码示例
121 ///
122 /// ```
123 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
124 ///
125 /// # fn example() -> anyhow::Result<()> {
126 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
127 /// let object_manager = ObjectsManager::new(credential);
128 /// let bucket = object_manager.bucket("test-bucket");
129 ///
130 /// let response = bucket.stat_object("test-key").call()?;
131 /// let object = response.into_body();
132 /// println!("fsize: {}", object.get_size_as_u64());
133 /// println!("hash: {}", object.get_hash_as_str());
134 /// println!("mime_type: {}", object.get_mime_type_as_str());
135 /// # Ok(())
136 /// # }
137 /// ```
138 ///
139 /// ##### 异步代码示例
140 ///
141 /// ```
142 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
143 ///
144 /// # async fn example() -> anyhow::Result<()> {
145 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
146 /// let object_manager = ObjectsManager::new(credential);
147 /// let bucket = object_manager.bucket("test-bucket");
148 ///
149 /// let response = bucket.stat_object("test-key").async_call().await?;
150 /// let object = response.into_body();
151 /// println!("fsize: {}", object.get_size_as_u64());
152 /// println!("hash: {}", object.get_hash_as_str());
153 /// println!("mime_type: {}", object.get_mime_type_as_str());
154 /// # Ok(())
155 /// # }
156 /// ```
157 #[inline]
158 pub fn stat_object<'a>(&'a self, object_name: &'a str) -> StatObjectBuilder<'a> {
159 StatObject::builder(Entry::new(self, object_name))
160 }
161
162 /// 创建对象复制操作构建器
163 ///
164 /// ##### 阻塞代码示例
165 ///
166 /// ```
167 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
168 ///
169 /// # fn example() -> anyhow::Result<()> {
170 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
171 /// let object_manager = ObjectsManager::new(credential);
172 /// let bucket = object_manager.bucket("test-bucket");
173 ///
174 /// bucket.copy_object_to("test-key", "test-bucket-2", "test-key").call()?;
175 /// # Ok(())
176 /// # }
177 /// ```
178 ///
179 /// ##### 异步代码示例
180 ///
181 /// ```
182 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
183 ///
184 /// # async fn example() -> anyhow::Result<()> {
185 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
186 /// let object_manager = ObjectsManager::new(credential);
187 /// let bucket = object_manager.bucket("test-bucket");
188 ///
189 /// bucket.copy_object_to("test-key", "test-bucket-2", "test-key").async_call().await?;
190 /// # Ok(())
191 /// # }
192 /// ```
193 #[inline]
194 pub fn copy_object_to<'a>(
195 &'a self,
196 from_object_name: &'a str,
197 to_bucket_name: &'a str,
198 to_object_name: &'a str,
199 ) -> CopyObjectBuilder<'a> {
200 CopyObject::builder(Entry::new(self, from_object_name), to_bucket_name, to_object_name)
201 }
202
203 /// 创建对象移动操作构建器
204 ///
205 /// ##### 阻塞代码示例
206 ///
207 /// ```
208 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
209 ///
210 /// # fn example() -> anyhow::Result<()> {
211 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
212 /// let object_manager = ObjectsManager::new(credential);
213 /// let bucket = object_manager.bucket("test-bucket");
214 ///
215 /// bucket.move_object_to("test-key", "test-bucket-2", "test-key").call()?;
216 /// # Ok(())
217 /// # }
218 /// ```
219 ///
220 /// ##### 异步代码示例
221 ///
222 /// ```
223 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
224 ///
225 /// # async fn example() -> anyhow::Result<()> {
226 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
227 /// let object_manager = ObjectsManager::new(credential);
228 /// let bucket = object_manager.bucket("test-bucket");
229 ///
230 /// bucket.move_object_to("test-key", "test-bucket-2", "test-key").async_call().await?;
231 /// # Ok(())
232 /// # }
233 /// ```
234 #[inline]
235 pub fn move_object_to<'a>(
236 &'a self,
237 from_object_name: &'a str,
238 to_bucket_name: &'a str,
239 to_object_name: &'a str,
240 ) -> MoveObjectBuilder<'a> {
241 MoveObject::builder(Entry::new(self, from_object_name), to_bucket_name, to_object_name)
242 }
243
244 /// 创建对象删除操作构建器
245 ///
246 /// ##### 阻塞代码示例
247 ///
248 /// ```
249 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
250 ///
251 /// # fn example() -> anyhow::Result<()> {
252 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
253 /// let object_manager = ObjectsManager::new(credential);
254 /// let bucket = object_manager.bucket("test-bucket");
255 ///
256 /// bucket.delete_object("test-key").call()?;
257 /// # Ok(())
258 /// # }
259 /// ```
260 ///
261 /// ##### 异步代码示例
262 ///
263 /// ```
264 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
265 ///
266 /// # async fn example() -> anyhow::Result<()> {
267 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
268 /// let object_manager = ObjectsManager::new(credential);
269 /// let bucket = object_manager.bucket("test-bucket");
270 ///
271 /// bucket.delete_object("test-key").async_call().await?;
272 /// # Ok(())
273 /// # }
274 /// ```
275 #[inline]
276 pub fn delete_object<'a>(&'a self, object_name: &'a str) -> DeleteObjectBuilder<'a> {
277 DeleteObject::builder(Entry::new(self, object_name))
278 }
279
280 /// 创建对象解冻操作构建器
281 ///
282 /// ##### 阻塞代码示例
283 ///
284 /// ```
285 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
286 ///
287 /// # fn example() -> anyhow::Result<()> {
288 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
289 /// let object_manager = ObjectsManager::new(credential);
290 /// let bucket = object_manager.bucket("test-bucket");
291 ///
292 /// bucket.restore_archived_object("test-key", 1).call()?;
293 /// # Ok(())
294 /// # }
295 /// ```
296 ///
297 /// ##### 异步代码示例
298 ///
299 /// ```
300 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
301 ///
302 /// # async fn example() -> anyhow::Result<()> {
303 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
304 /// let object_manager = ObjectsManager::new(credential);
305 /// let bucket = object_manager.bucket("test-bucket");
306 ///
307 /// bucket.restore_archived_object("test-key", 1).async_call().await?;
308 /// # Ok(())
309 /// # }
310 /// ```
311 #[inline]
312 pub fn restore_archived_object<'a>(
313 &'a self,
314 object_name: &'a str,
315 freeze_after_days: usize,
316 ) -> UnfreezeObjectBuilder<'a> {
317 UnfreezeObject::builder(Entry::new(self, object_name), freeze_after_days)
318 }
319
320 /// 创建对象类型设置操作构建器
321 ///
322 /// ##### 阻塞代码示例
323 ///
324 /// ```
325 /// use qiniu_objects_manager::{apis::{credential::Credential, upload_token::FileType}, ObjectsManager};
326 ///
327 /// # fn example() -> anyhow::Result<()> {
328 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
329 /// let object_manager = ObjectsManager::new(credential);
330 /// let bucket = object_manager.bucket("test-bucket");
331 ///
332 /// bucket.set_object_type("test-key", FileType::Archive).call()?;
333 /// # Ok(())
334 /// # }
335 /// ```
336 ///
337 /// ##### 异步代码示例
338 ///
339 /// ```
340 /// use qiniu_objects_manager::{apis::{credential::Credential, upload_token::FileType}, ObjectsManager};
341 ///
342 /// # async fn example() -> anyhow::Result<()> {
343 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
344 /// let object_manager = ObjectsManager::new(credential);
345 /// let bucket = object_manager.bucket("test-bucket");
346 ///
347 /// bucket.set_object_type("test-key", FileType::Archive).async_call().await?;
348 /// # Ok(())
349 /// # }
350 /// ```
351 #[inline]
352 pub fn set_object_type<'a>(&'a self, object_name: &'a str, object_type: FileType) -> SetObjectTypeBuilder<'a> {
353 SetObjectType::builder(Entry::new(self, object_name), object_type)
354 }
355
356 /// 创建对象状态设置操作构建器
357 ///
358 /// ##### 阻塞代码示例
359 ///
360 /// ```
361 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
362 ///
363 /// # async fn example() -> anyhow::Result<()> {
364 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
365 /// let object_manager = ObjectsManager::new(credential);
366 /// let bucket = object_manager.bucket("test-bucket");
367 ///
368 /// bucket.modify_object_status("test-key", true).call()?;
369 /// # Ok(())
370 /// # }
371 /// ```
372 ///
373 /// ##### 异步代码示例
374 ///
375 /// ```
376 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager};
377 ///
378 /// # async fn example() -> anyhow::Result<()> {
379 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
380 /// let object_manager = ObjectsManager::new(credential);
381 /// let bucket = object_manager.bucket("test-bucket");
382 ///
383 /// bucket.modify_object_status("test-key", true).async_call().await?;
384 /// # Ok(())
385 /// # }
386 /// ```
387 #[inline]
388 pub fn modify_object_status<'a>(&'a self, object_name: &'a str, disable: bool) -> ModifyObjectStatusBuilder<'a> {
389 ModifyObjectStatus::builder(Entry::new(self, object_name), disable)
390 }
391
392 /// 创建对象元信息设置操作构建器
393 ///
394 /// ```
395 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager, mime::APPLICATION_JSON};
396 ///
397 /// # async fn example() -> anyhow::Result<()> {
398 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
399 /// let object_manager = ObjectsManager::new(credential);
400 /// let bucket = object_manager.bucket("test-bucket");
401 ///
402 /// bucket.modify_object_metadata("test-key", APPLICATION_JSON).async_call().await?;
403 /// # Ok(())
404 /// # }
405 /// ```
406 #[inline]
407 pub fn modify_object_metadata<'a>(
408 &'a self,
409 object_name: &'a str,
410 mime_type: Mime,
411 ) -> ModifyObjectMetadataBuilder<'a> {
412 ModifyObjectMetadata::builder(Entry::new(self, object_name), mime_type)
413 }
414
415 /// 创建对象生命周期设置操作构建器
416 ///
417 /// ##### 阻塞代码示例
418 ///
419 /// ```
420 /// use qiniu_objects_manager::{AfterDays, apis::credential::Credential, ObjectsManager};
421 ///
422 /// # async fn example() -> anyhow::Result<()> {
423 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
424 /// let object_manager = ObjectsManager::new(credential);
425 /// let bucket = object_manager.bucket("test-bucket");
426 ///
427 /// bucket.modify_object_life_cycle("test-key").delete_after_days(AfterDays::new(5)).call()?;
428 /// # Ok(())
429 /// # }
430 /// ```
431 ///
432 /// ##### 异步代码示例
433 ///
434 /// ```
435 /// use qiniu_objects_manager::{AfterDays, apis::credential::Credential, ObjectsManager};
436 ///
437 /// # async fn example() -> anyhow::Result<()> {
438 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
439 /// let object_manager = ObjectsManager::new(credential);
440 /// let bucket = object_manager.bucket("test-bucket");
441 ///
442 /// bucket.modify_object_life_cycle("test-key").delete_after_days(AfterDays::new(5)).async_call().await?;
443 /// # Ok(())
444 /// # }
445 /// ```
446 #[inline]
447 pub fn modify_object_life_cycle<'a>(&'a self, object_name: &'a str) -> ModifyObjectLifeCycleBuilder<'a> {
448 ModifyObjectLifeCycle::builder(Entry::new(self, object_name))
449 }
450
451 /// 创建批量操作
452 ///
453 /// ##### 阻塞代码示例
454 ///
455 /// ```
456 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager, OperationProvider};
457 ///
458 /// # fn example() -> anyhow::Result<()> {
459 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
460 /// let object_manager = ObjectsManager::new(credential);
461 /// let bucket = object_manager.bucket("test-bucket");
462 /// let mut ops = bucket.batch_ops();
463 /// ops.add_operation(bucket.stat_object("test-file-1"));
464 /// ops.add_operation(bucket.stat_object("test-file-2"));
465 /// ops.add_operation(bucket.stat_object("test-file-3"));
466 /// ops.add_operation(bucket.stat_object("test-file-4"));
467 /// ops.add_operation(bucket.stat_object("test-file-5"));
468 /// let mut iter = ops.call();
469 /// while let Some(object) = iter.next() {
470 /// let object = object?;
471 /// println!("fsize: {:?}", object.get_size_as_u64());
472 /// println!("hash: {:?}", object.get_hash_as_str());
473 /// println!("mime_type: {:?}", object.get_mime_type_as_str());
474 /// }
475 /// # Ok(())
476 /// # }
477 /// ```
478 ///
479 /// ##### 异步代码示例
480 ///
481 /// ```
482 /// use qiniu_objects_manager::{apis::credential::Credential, ObjectsManager, OperationProvider};
483 /// use futures::stream::TryStreamExt;
484 ///
485 /// # async fn example() -> anyhow::Result<()> {
486 /// let credential = Credential::new("abcdefghklmnopq", "1234567890");
487 /// let object_manager = ObjectsManager::new(credential);
488 /// let bucket = object_manager.bucket("test-bucket");
489 /// let mut ops = bucket.batch_ops();
490 /// ops.add_operation(bucket.stat_object("test-file-1"));
491 /// ops.add_operation(bucket.stat_object("test-file-2"));
492 /// ops.add_operation(bucket.stat_object("test-file-3"));
493 /// ops.add_operation(bucket.stat_object("test-file-4"));
494 /// ops.add_operation(bucket.stat_object("test-file-5"));
495 /// let mut stream = ops.async_call();
496 /// while let Some(object) = stream.try_next().await? {
497 /// println!("fsize: {:?}", object.get_size_as_u64());
498 /// println!("hash: {:?}", object.get_hash_as_str());
499 /// println!("mime_type: {:?}", object.get_mime_type_as_str());
500 /// }
501 /// # Ok(())
502 /// # }
503 /// ```
504 #[inline]
505 pub fn batch_ops(&self) -> BatchOperations<'_> {
506 BatchOperations::new(self)
507 }
508
509 pub(super) fn region_provider(&self) -> IOResult<&dyn RegionsProvider> {
510 self.0
511 .region_provider
512 .as_ref()
513 .map(|r| Ok(r as &dyn RegionsProvider))
514 .unwrap_or_else(|| {
515 self.0
516 .bucket_regions_provider
517 .get_or_try_init(|| {
518 Ok(self.0.objects_manager.queryer().query(
519 self.0
520 .objects_manager
521 .credential()
522 .get(Default::default())?
523 .access_key()
524 .to_owned(),
525 self.name().to_owned(),
526 ))
527 })
528 .map(|r| r as &dyn RegionsProvider)
529 })
530 }
531
532 #[cfg(feature = "async")]
533 pub(super) async fn async_region_provider(&self) -> IOResult<&dyn RegionsProvider> {
534 return if let Some(region_provider) = self.0.region_provider.as_ref() {
535 Ok(region_provider)
536 } else {
537 self.0
538 .async_bucket_regions_provider
539 .get_or_try_init(create_region_provider(&self.0.objects_manager, self.name()))
540 .await
541 .map(|r| r as &dyn RegionsProvider)
542 };
543
544 async fn create_region_provider(
545 objects_manager: &ObjectsManager,
546 bucket_name: &BucketName,
547 ) -> IOResult<BucketRegionsProvider> {
548 Ok(objects_manager.queryer().query(
549 objects_manager
550 .credential()
551 .async_get(Default::default())
552 .await?
553 .access_key()
554 .to_owned(),
555 bucket_name.to_owned(),
556 ))
557 }
558 }
559
560 #[allow(dead_code)]
561 fn assert() {
562 assert_impl!(Send: Self);
563 assert_impl!(Sync: Self);
564 }
565}
566
567/// 列举操作构建器
568///
569/// 可以通过 [`Bucket::list`] 方法获取该构建器。
570#[must_use]
571#[derive(Debug)]
572pub struct ListBuilder<'a> {
573 bucket: &'a Bucket,
574 limit: Option<usize>,
575 prefix: Option<Cow<'a, str>>,
576 marker: Option<Cow<'a, str>>,
577 version: ListVersion,
578 need_parts: bool,
579 callbacks: Callbacks<'a>,
580}
581
582impl<'a> ListBuilder<'a> {
583 fn new(bucket: &'a Bucket) -> Self {
584 Self {
585 bucket,
586 limit: Default::default(),
587 prefix: Default::default(),
588 marker: Default::default(),
589 version: Default::default(),
590 need_parts: Default::default(),
591 callbacks: Default::default(),
592 }
593 }
594
595 #[inline]
596 /// 设置列举限制
597 pub fn limit(&mut self, limit: usize) -> &mut Self {
598 self.limit = Some(limit);
599 self
600 }
601
602 #[inline]
603 /// 设置对象名称前缀匹配字符串
604 pub fn prefix(&mut self, prefix: impl Into<Cow<'a, str>>) -> &mut Self {
605 self.prefix = Some(prefix.into());
606 self
607 }
608
609 #[inline]
610 /// 设置上一次列举返回的位置标记
611 pub fn marker(&mut self, marker: impl Into<Cow<'a, str>>) -> &mut Self {
612 self.marker = Some(marker.into());
613 self
614 }
615
616 #[inline]
617 /// 设置列举 API 版本
618 pub fn version(&mut self, version: ListVersion) -> &mut Self {
619 self.version = version;
620 self
621 }
622
623 /// 设置是否需要返回分片信息
624 #[inline]
625 pub fn need_parts(&mut self) -> &mut Self {
626 self.need_parts = true;
627 self
628 }
629
630 /// 设置请求前回调函数
631 #[inline]
632 pub fn before_request_callback(
633 &mut self,
634 callback: impl FnMut(&mut RequestBuilderParts<'_>) -> AnyResult<()> + Send + Sync + 'a,
635 ) -> &mut Self {
636 self.callbacks.insert_before_request_callback(callback);
637 self
638 }
639
640 /// 设置响应成功回调函数
641 #[inline]
642 pub fn after_response_ok_callback(
643 &mut self,
644 callback: impl FnMut(&mut ResponseParts) -> AnyResult<()> + Send + Sync + 'a,
645 ) -> &mut Self {
646 self.callbacks.insert_after_response_ok_callback(callback);
647 self
648 }
649
650 /// 设置响应失败回调函数
651 #[inline]
652 pub fn after_response_error_callback(
653 &mut self,
654 callback: impl FnMut(&mut ResponseError) -> AnyResult<()> + Send + Sync + 'a,
655 ) -> &mut Self {
656 self.callbacks.insert_after_response_error_callback(callback);
657 self
658 }
659
660 /// 创建对象列举迭代器
661 ///
662 /// 对象列举迭代器采用阻塞 API 列举对象信息
663 ///
664 /// 该方法的的异步版本为 [`Self::stream`]。
665 #[inline]
666 pub fn iter(&mut self) -> ListIter<'a> {
667 let owned = self.take_self();
668 ListIter::new(
669 owned.bucket,
670 owned.limit,
671 owned.prefix,
672 owned.marker,
673 owned.need_parts,
674 owned.version,
675 owned.callbacks,
676 )
677 }
678
679 /// 创建对象列举流
680 ///
681 /// 对象列举流采用异步 API 列举对象信息
682 #[inline]
683 #[cfg(feature = "async")]
684 #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
685 pub fn stream(&mut self) -> ListStream<'a> {
686 let owned = self.take_self();
687 ListStream::new(
688 owned.bucket,
689 owned.limit,
690 owned.prefix,
691 owned.marker,
692 owned.need_parts,
693 owned.version,
694 owned.callbacks,
695 )
696 }
697
698 fn take_self(&mut self) -> Self {
699 Self {
700 bucket: self.bucket,
701 limit: take(&mut self.limit),
702 prefix: take(&mut self.prefix),
703 marker: take(&mut self.marker),
704 need_parts: take(&mut self.need_parts),
705 version: take(&mut self.version),
706 callbacks: take(&mut self.callbacks),
707 }
708 }
709
710 #[allow(dead_code)]
711 fn assert() {
712 assert_impl!(Send: Self);
713 assert_impl!(Sync: Self);
714 }
715}