1use crate::bucket::Bucket;
60#[cfg(feature = "blocking")]
61use crate::builder::RcPointer;
62use crate::builder::{ArcPointer, BuilderError, PointerFamily};
63use crate::client::ClientArc;
64#[cfg(feature = "blocking")]
65use crate::client::ClientRc;
66use crate::config::BucketBase;
67use crate::decode::{InnerListError, ListError, RefineObject, RefineObjectList};
68#[cfg(feature = "blocking")]
69use crate::file::blocking::AlignBuilder as BlockingAlignBuilder;
70use crate::file::AlignBuilder;
71use crate::types::object::ObjectPathInner;
72use crate::types::{
73 core::SetOssQuery,
74 object::{
75 CommonPrefixes, InvalidObjectDir, InvalidObjectPath, ObjectBase, ObjectDir, ObjectPath,
76 },
77 CanonicalizedResource, Query, QueryKey, QueryValue, CONTINUATION_TOKEN,
78};
79use crate::{BucketName, Client, EndPoint, KeyId, KeySecret};
80use async_stream::try_stream;
81use chrono::{DateTime, NaiveDateTime, Utc};
82use futures_core::stream::Stream;
83use http::Method;
84use oss_derive::oss_gen_rc;
85use url::Url;
86
87#[cfg(feature = "blocking")]
88use std::rc::Rc;
89use std::{
90 error::Error,
91 fmt::{self, Display},
92 num::ParseIntError,
93 sync::Arc,
94 vec::IntoIter,
95};
96
97pub mod content;
98pub use content::Content;
99
100#[cfg(test)]
101mod test;
102
103#[derive(Clone)]
107#[non_exhaustive]
108pub struct ObjectList<P: PointerFamily = ArcPointer, Item = Object<P>> {
109 pub(crate) bucket: BucketBase,
110 prefix: Option<ObjectDir<'static>>,
111 max_keys: u32,
112 key_count: u64,
113 object_list: Vec<Item>,
115 next_continuation_token: String,
116 common_prefixes: CommonPrefixes,
117 client: P::PointerType,
118 search_query: Query,
119}
120
121pub type Objects<Item = Object<ArcPointer>> = ObjectList<ArcPointer, Item>;
123#[cfg(feature = "blocking")]
125pub type ObjectsBlocking<Item = Object<RcPointer>> = ObjectList<RcPointer, Item>;
126
127#[derive(Clone, Debug)]
129#[non_exhaustive]
130pub struct Object<PointerSel: PointerFamily = ArcPointer> {
131 pub(crate) base: ObjectBase<PointerSel>,
132 last_modified: DateTime<Utc>,
133 etag: String,
134 _type: String,
135 size: u64,
136 storage_class: StorageClass,
137}
138
139pub type ObjectArc = Object<ArcPointer>;
141
142impl<T: PointerFamily, Item> fmt::Debug for ObjectList<T, Item> {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 f.debug_struct("ObjectList")
145 .field("bucket", &self.bucket)
146 .field("prefix", &self.prefix)
147 .field("max_keys", &self.max_keys)
148 .field("key_count", &self.key_count)
149 .field("next_continuation_token", &self.next_continuation_token)
150 .field("common_prefixes", &self.common_prefixes)
151 .field("search_query", &self.search_query)
152 .finish()
153 }
154}
155
156impl<P: PointerFamily, Item> Default for ObjectList<P, Item> {
157 fn default() -> Self {
158 Self {
159 bucket: BucketBase::default(),
160 prefix: Option::default(),
161 max_keys: u32::default(),
162 key_count: u64::default(),
163 object_list: Vec::new(),
164 next_continuation_token: String::default(),
165 common_prefixes: CommonPrefixes::default(),
166 client: P::PointerType::default(),
167 search_query: Query::default(),
168 }
170 }
171}
172
173impl<T: PointerFamily, Item> AsMut<Query> for ObjectList<T, Item> {
174 fn as_mut(&mut self) -> &mut Query {
175 &mut self.search_query
176 }
177}
178
179impl<T: PointerFamily, Item> AsRef<BucketBase> for ObjectList<T, Item> {
180 fn as_ref(&self) -> &BucketBase {
181 &self.bucket
182 }
183}
184
185impl<T: PointerFamily, Item> AsRef<BucketName> for ObjectList<T, Item> {
186 fn as_ref(&self) -> &BucketName {
187 self.bucket.as_ref()
188 }
189}
190
191impl<T: PointerFamily, Item> AsRef<EndPoint> for ObjectList<T, Item> {
192 fn as_ref(&self) -> &EndPoint {
193 self.bucket.as_ref()
194 }
195}
196
197impl<T: PointerFamily, Item> ObjectList<T, Item> {
198 #[allow(clippy::too_many_arguments)]
200 pub fn new<Q: IntoIterator<Item = (QueryKey, QueryValue)>>(
201 bucket: BucketBase,
202 prefix: Option<ObjectDir<'static>>,
203 max_keys: u32,
204 key_count: u64,
205 object_list: Vec<Item>,
206 next_continuation_token: Option<String>,
207 client: T::PointerType,
208 search_query: Q,
209 ) -> Self {
210 Self {
211 bucket,
212 prefix,
213 max_keys,
214 key_count,
215 object_list,
216 next_continuation_token: next_continuation_token.unwrap_or_default(),
217 common_prefixes: CommonPrefixes::default(),
218 client,
219 search_query: Query::from_iter(search_query),
220 }
222 }
223
224 pub fn bucket(&self) -> &BucketBase {
226 &self.bucket
227 }
228
229 pub fn prefix(&self) -> &Option<ObjectDir<'static>> {
231 &self.prefix
232 }
233
234 pub fn common_prefixes(&self) -> &CommonPrefixes {
236 &self.common_prefixes
237 }
238
239 pub fn set_common_prefixes<P: IntoIterator<Item = ObjectDir<'static>>>(&mut self, prefixes: P) {
241 self.common_prefixes = CommonPrefixes::from_iter(prefixes);
242 }
243
244 pub fn max_keys(&self) -> &u32 {
246 &self.max_keys
247 }
248
249 pub fn key_count(&self) -> &u64 {
251 &self.key_count
252 }
253
254 pub fn next_continuation_token_str(&self) -> &String {
257 &self.next_continuation_token
258 }
259
260 pub fn search_query(&self) -> &Query {
262 &self.search_query
263 }
264
265 pub fn next_query(&self) -> Option<Query> {
270 if !self.next_continuation_token.is_empty() {
271 let mut search_query = self.search_query.clone();
272 search_query.insert(CONTINUATION_TOKEN, self.next_continuation_token.to_owned());
273 Some(search_query)
274 } else {
275 None
276 }
277 }
278
279 pub fn object_iter(self) -> IntoIter<Item> {
281 self.object_list.into_iter()
282 }
283}
284
285#[oss_gen_rc]
286impl<Item> ObjectList<ArcPointer, Item> {
287 pub(crate) fn set_client(&mut self, client: Arc<ClientArc>) {
289 self.client = client;
290 }
291
292 pub(crate) fn from_bucket(
293 bucket: &Bucket<ArcPointer>,
294 capacity: usize,
295 ) -> ObjectList<ArcPointer> {
296 ObjectList::<ArcPointer> {
297 bucket: bucket.base.clone(),
298 client: Arc::clone(&bucket.client),
299 object_list: Vec::with_capacity(capacity),
300 ..Default::default()
301 }
302 }
303
304 pub(crate) fn client(&self) -> Arc<ClientArc> {
306 Arc::clone(&self.client)
307 }
308
309 fn clone_base(&self) -> Self {
310 Self {
311 client: Arc::clone(&self.client),
312 bucket: self.bucket.clone(),
313 search_query: self.search_query.clone(),
314 max_keys: self.max_keys,
315 object_list: Vec::with_capacity(self.max_keys as usize),
316 ..Default::default()
317 }
318 }
319}
320
321pub trait InitObject<Target> {
330 fn init_object(&mut self) -> Option<Target>;
334}
335
336impl InitObject<Object<ArcPointer>> for ObjectList<ArcPointer, Object<ArcPointer>> {
337 fn init_object(&mut self) -> Option<Object<ArcPointer>> {
338 Some(Object::from_bucket(Arc::new(self.bucket.clone())))
339 }
340}
341
342#[cfg(feature = "blocking")]
343impl InitObject<Object<RcPointer>> for ObjectList<RcPointer, Object<RcPointer>> {
344 fn init_object(&mut self) -> Option<Object<RcPointer>> {
345 Some(Object::<RcPointer>::from_bucket(Rc::new(
346 self.bucket.clone(),
347 )))
348 }
349}
350
351impl ObjectList<ArcPointer> {
352 pub async fn get_next_list(&self) -> Result<ObjectList<ArcPointer>, ExtractListError> {
355 match self.next_query() {
356 None => Err(ExtractListError {
357 kind: ExtractListErrorKind::NoMoreFile,
358 }),
359 Some(query) => {
360 let mut url = self.bucket.to_url();
361 url.set_oss_query(&query);
362
363 let canonicalized = CanonicalizedResource::from_bucket_query(&self.bucket, &query);
364
365 let response = self
366 .builder(Method::GET, url, canonicalized)?
367 .send_adjust_error()
368 .await?;
369
370 let mut list = ObjectList::<ArcPointer> {
371 client: self.client(),
372 bucket: self.bucket.clone(),
373 object_list: Vec::with_capacity(query.get_max_keys()),
374 ..Default::default()
375 };
376
377 list.decode(&response.text().await?, Self::init_object)?;
378
379 list.set_search_query(query);
380 Ok(list)
381 }
382 }
383 }
384
385 pub fn into_stream(self) -> impl Stream<Item = Result<Self, ExtractListError>> {
417 try_stream! {
418 let result = self.get_next_list().await?;
419 yield result;
420 }
421 }
422}
423
424impl<Item> ObjectList<ArcPointer, Item>
425where
426 Self: InitObject<Item>,
427{
428 pub async fn get_next_base<E>(&mut self) -> Option<Result<Self, ExtractListError>>
432 where
433 Item: RefineObject<E>,
434 E: Error + 'static,
435 {
436 match self.next_query() {
437 None => None,
438 Some(query) => {
439 let mut list = self.clone_base();
440 list.search_query = query.clone();
441 let res = self.client().base_object_list(query, &mut list).await;
442 Some(res.map(|_| list))
443 }
444 }
445 }
446}
447
448#[cfg(feature = "blocking")]
449impl ObjectList<RcPointer> {
450 pub fn get_object_list(&self) -> Result<Self, ExtractListError> {
452 let mut list = ObjectList::<RcPointer>::clone_base(self);
453
454 let (bucket_url, resource) = self.bucket.get_url_resource(&self.search_query);
455
456 let response = self
457 .builder(Method::GET, bucket_url, resource)?
458 .send_adjust_error()?;
459
460 list.decode(&response.text()?, ObjectList::<RcPointer>::init_object)
461 .map_err(ExtractListError::from)?;
462
463 Ok(list)
464 }
465}
466
467impl<T: PointerFamily, Item> ObjectList<T, Item> {
468 #[inline]
470 pub fn set_search_query(&mut self, search_query: Query) {
471 self.search_query = search_query;
472 }
473
474 pub fn set_bucket(&mut self, bucket: BucketBase) {
476 self.bucket = bucket;
477 }
478
479 pub fn bucket_name(&self) -> &str {
481 self.bucket.name()
482 }
483
484 pub fn to_vec(self) -> Vec<Item> {
486 self.object_list
487 }
488
489 pub fn len(&self) -> usize {
491 self.object_list.len()
492 }
493
494 pub fn is_empty(&self) -> bool {
496 self.object_list.is_empty()
497 }
498}
499
500impl<T: PointerFamily> Default for Object<T> {
501 fn default() -> Self {
502 Object {
503 base: ObjectBase::<T>::default(),
504 last_modified: DateTime::<Utc>::from_utc(
505 #[allow(clippy::unwrap_used)]
506 NaiveDateTime::from_timestamp_opt(0, 0).unwrap(),
507 Utc,
508 ),
509 etag: String::default(),
510 _type: String::default(),
511 size: 0,
512 storage_class: StorageClass::default(),
513 }
514 }
515}
516
517impl<T: PointerFamily> AsRef<ObjectPath> for Object<T> {
518 fn as_ref(&self) -> &ObjectPath {
519 self.base.as_ref()
520 }
521}
522
523impl<T: PointerFamily> AsRef<DateTime<Utc>> for Object<T> {
524 fn as_ref(&self) -> &DateTime<Utc> {
525 &self.last_modified
526 }
527}
528
529impl<T: PointerFamily> AsRef<StorageClass> for Object<T> {
530 fn as_ref(&self) -> &StorageClass {
531 &self.storage_class
532 }
533}
534
535impl<T: PointerFamily> Object<T> {
536 pub fn new(
538 bucket: T::Bucket,
539 path: ObjectPath,
540 last_modified: DateTime<Utc>,
541 etag: String,
542 _type: String,
543 size: u64,
544 storage_class: StorageClass,
545 ) -> Self {
546 let base = ObjectBase::<T>::new2(bucket, path);
547 Self {
548 base,
549 last_modified,
550 etag,
551 _type,
552 size,
553 storage_class,
554 }
555 }
556
557 pub(crate) fn from_bucket(bucket: T::Bucket) -> Self {
558 Self {
559 base: ObjectBase::<T>::init_with_bucket(bucket),
560 ..Default::default()
561 }
562 }
563
564 #[inline]
566 pub fn base(&self) -> &ObjectBase<T> {
567 &self.base
568 }
569
570 #[inline]
572 pub fn set_base(&mut self, base: ObjectBase<T>) {
573 self.base = base;
574 }
575
576 #[inline]
578 pub fn last_modified(&self) -> &DateTime<Utc> {
579 &self.last_modified
580 }
581
582 #[inline]
584 pub fn set_last_modified(&mut self, last_modified: DateTime<Utc>) {
585 self.last_modified = last_modified;
586 }
587
588 #[inline]
590 pub fn etag(&self) -> &String {
591 &self.etag
592 }
593
594 #[inline]
596 pub fn set_etag(&mut self, etag: String) {
597 self.etag = etag
598 }
599
600 #[inline]
602 pub fn get_type_string(&self) -> &String {
603 &self._type
604 }
605
606 #[inline]
608 pub fn set_type_string(&mut self, _type: String) {
609 self._type = _type;
610 }
611
612 #[inline]
614 pub fn size(&self) -> u64 {
615 self.size
616 }
617
618 #[inline]
620 pub fn set_size(&mut self, size: u64) {
621 self.size = size;
622 }
623
624 #[inline]
626 pub fn storage_class(&self) -> &StorageClass {
627 &self.storage_class
628 }
629
630 #[inline]
632 pub fn set_storage_class(&mut self, storage_class: StorageClass) {
633 self.storage_class = storage_class;
634 }
635
636 pub fn pieces(
638 self,
639 ) -> (
640 ObjectBase<T>,
641 DateTime<Utc>,
642 String,
643 String,
644 u64,
645 StorageClass,
646 ) {
647 (
648 self.base,
649 self.last_modified,
650 self.etag,
651 self._type,
652 self.size,
653 self.storage_class,
654 )
655 }
656
657 pub fn path(&self) -> ObjectPath {
659 self.base.path()
660 }
661
662 #[doc(hidden)]
663 pub fn path_string(&self) -> String {
664 self.base.path().to_string()
665 }
666}
667
668impl Object<ArcPointer> {
669 #[cfg(test)]
670 pub fn test_path(path: &'static str) -> Self {
671 let mut object = Self::default();
672 object.set_base(ObjectBase::<ArcPointer>::new2(
673 Arc::new(BucketBase::default()),
674 path.try_into().unwrap(),
675 ));
676 object
677 }
678}
679
680impl<T: PointerFamily> From<Object<T>> for ObjectPathInner<'static> {
681 #[inline]
682 fn from(obj: Object<T>) -> Self {
683 obj.base.path
684 }
685}
686
687#[oss_gen_rc]
688impl Object<ArcPointer> {
689 pub fn builder(path: ObjectPath) -> ObjectBuilder<ArcPointer> {
714 ObjectBuilder::<ArcPointer>::new(Arc::default(), path)
715 }
716
717 pub fn to_sign_url(&self, key: &KeyId, secret: &KeySecret, expires: i64) -> Url {
719 self.base.to_sign_url(key, secret, expires)
720 }
721}
722
723pub struct ObjectBuilder<T: PointerFamily = ArcPointer> {
725 object: Object<T>,
726}
727
728impl<T: PointerFamily> ObjectBuilder<T> {
729 pub fn new(bucket: T::Bucket, path: ObjectPath) -> Self {
731 let base = ObjectBase::<T>::new2(bucket, path);
732 Self {
733 object: Object {
734 base,
735 last_modified: DateTime::<Utc>::from_utc(
736 #[allow(clippy::unwrap_used)]
737 NaiveDateTime::from_timestamp_opt(0, 0).unwrap(),
738 Utc,
739 ),
740 ..Default::default()
741 },
742 }
743 }
744
745 pub fn bucket(&mut self, bucket: T::Bucket) -> &mut Self {
747 self.object.base.set_bucket(bucket);
748 self
749 }
750
751 pub fn last_modified(&mut self, date: DateTime<Utc>) -> &mut Self {
753 self.object.last_modified = date;
754 self
755 }
756
757 pub fn etag(&mut self, etag: String) -> &mut Self {
759 self.object.etag = etag;
760 self
761 }
762
763 pub fn set_type(&mut self, _type: String) -> &mut Self {
765 self.object._type = _type;
766 self
767 }
768
769 pub fn size(&mut self, size: u64) -> &mut Self {
771 self.object.size = size;
772 self
773 }
774
775 pub fn storage_class(&mut self, storage_class: StorageClass) -> &mut Self {
777 self.object.storage_class = storage_class;
778 self
779 }
780
781 pub fn build(self) -> Object<T> {
783 self.object
784 }
785}
786
787#[oss_gen_rc]
788impl ObjectBuilder<ArcPointer> {
789 pub fn bucket_base(&mut self, base: BucketBase) -> &mut Self {
791 self.object.base.set_bucket(Arc::new(base));
792 self
793 }
794}
795
796impl<T: PointerFamily> RefineObject<BuildInItemError> for Object<T> {
797 #[inline]
798 fn set_key(&mut self, key: &str) -> Result<(), BuildInItemError> {
799 self.base
800 .set_path(key.to_owned())
801 .map_err(|e| BuildInItemError {
802 source: key.to_string(),
803 kind: BuildInItemErrorKind::BasePath(e),
804 })
805 }
806
807 #[inline]
808 fn set_last_modified(&mut self, value: &str) -> Result<(), BuildInItemError> {
809 self.last_modified = value.parse().map_err(|e| BuildInItemError {
810 source: value.to_string(),
811 kind: BuildInItemErrorKind::LastModified(e),
812 })?;
813 Ok(())
814 }
815
816 #[inline]
817 fn set_etag(&mut self, value: &str) -> Result<(), BuildInItemError> {
818 self.etag = value.to_string();
819 Ok(())
820 }
821
822 #[inline]
823 fn set_type(&mut self, value: &str) -> Result<(), BuildInItemError> {
824 self._type = value.to_string();
825 Ok(())
826 }
827
828 #[inline]
829 fn set_size(&mut self, size: &str) -> Result<(), BuildInItemError> {
830 self.size = size.parse().map_err(|e| BuildInItemError {
831 source: size.to_string(),
832 kind: BuildInItemErrorKind::Size(e),
833 })?;
834 Ok(())
835 }
836
837 #[inline]
838 fn set_storage_class(&mut self, storage_class: &str) -> Result<(), BuildInItemError> {
839 self.storage_class = StorageClass::new(storage_class).ok_or(BuildInItemError {
840 source: storage_class.to_string(),
841 kind: BuildInItemErrorKind::InvalidStorageClass,
842 })?;
843 Ok(())
844 }
845}
846
847#[derive(Debug)]
849#[non_exhaustive]
850pub struct BuildInItemError {
851 source: String,
852 kind: BuildInItemErrorKind,
853}
854
855impl BuildInItemError {
856 #[cfg(test)]
857 pub(crate) fn test_new() -> Self {
858 Self {
859 source: "foo".to_string(),
860 kind: BuildInItemErrorKind::InvalidStorageClass,
861 }
862 }
863
864 pub(crate) fn new<K: Into<BuildInItemErrorKind>>(kind: K, source: &str) -> Self {
865 Self {
866 source: source.to_owned(),
867 kind: kind.into(),
868 }
869 }
870}
871
872impl Display for BuildInItemError {
873 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874 use BuildInItemErrorKind::*;
875 let kind = match &self.kind {
876 Size(_) => "size",
877 BasePath(_) => "base-path",
878 LastModified(_) => "last-modified",
879 InvalidStorageClass => "storage-class",
880 };
881 write!(f, "parse {kind} failed, gived str: {}", self.source)
882 }
883}
884
885impl Error for BuildInItemError {
886 fn source(&self) -> Option<&(dyn Error + 'static)> {
887 use BuildInItemErrorKind::*;
888 match &self.kind {
889 Size(e) => Some(e),
890 BasePath(e) => Some(e),
891 LastModified(e) => Some(e),
892 InvalidStorageClass => None,
893 }
894 }
895}
896
897#[derive(Debug)]
899#[non_exhaustive]
900pub(crate) enum BuildInItemErrorKind {
901 Size(ParseIntError),
903
904 BasePath(InvalidObjectPath),
906
907 LastModified(chrono::ParseError),
909
910 InvalidStorageClass,
914}
915
916impl From<InvalidObjectPath> for BuildInItemErrorKind {
917 fn from(value: InvalidObjectPath) -> Self {
918 Self::BasePath(value)
919 }
920}
921
922impl<P: PointerFamily, Item: RefineObject<E>, E: Error + 'static>
923 RefineObjectList<Item, ObjectListError, E> for ObjectList<P, Item>
924{
925 #[inline]
926 fn set_key_count(&mut self, key_count: &str) -> Result<(), ObjectListError> {
927 self.key_count = key_count.parse().map_err(|e| ObjectListError {
928 source: key_count.to_owned(),
929 kind: ObjectListErrorKind::KeyCount(e),
930 })?;
931 Ok(())
932 }
933
934 #[inline]
935 fn set_prefix(&mut self, prefix: &str) -> Result<(), ObjectListError> {
936 if prefix.is_empty() {
937 self.prefix = None;
938 } else {
939 let mut string = String::from(prefix);
940 string += "/";
941 self.prefix = Some(string.parse().map_err(|e| ObjectListError {
942 source: prefix.to_owned(),
943 kind: ObjectListErrorKind::Prefix(e),
944 })?)
945 }
946 Ok(())
947 }
948
949 #[inline]
950 fn set_common_prefix(
951 &mut self,
952 list: &[std::borrow::Cow<'_, str>],
953 ) -> Result<(), ObjectListError> {
954 self.common_prefixes = Vec::with_capacity(list.len());
955 for val in list.iter() {
956 self.common_prefixes
957 .push(val.parse().map_err(|e| ObjectListError {
958 source: val.to_string(),
959 kind: ObjectListErrorKind::CommonPrefix(e),
960 })?);
961 }
962 Ok(())
963 }
964
965 #[inline]
966 fn set_max_keys(&mut self, max_keys: &str) -> Result<(), ObjectListError> {
967 self.max_keys = max_keys.parse().map_err(|e| ObjectListError {
968 source: max_keys.to_string(),
969 kind: ObjectListErrorKind::MaxKeys(e),
970 })?;
971 Ok(())
972 }
973
974 #[inline]
975 fn set_next_continuation_token_str(&mut self, token: &str) -> Result<(), ObjectListError> {
976 self.next_continuation_token = token.to_owned();
977 Ok(())
978 }
979
980 #[inline]
981 fn set_list(&mut self, list: Vec<Item>) -> Result<(), ObjectListError> {
982 self.object_list = list;
983 Ok(())
984 }
985}
986
987#[derive(Debug)]
989#[non_exhaustive]
990pub struct ObjectListError {
991 source: String,
992 kind: ObjectListErrorKind,
993}
994
995impl ObjectListError {
996 #[cfg(test)]
997 pub(crate) fn test_new() -> Self {
998 Self {
999 source: "foo".to_string(),
1000 kind: ObjectListErrorKind::Bar,
1001 }
1002 }
1003}
1004
1005impl Display for ObjectListError {
1006 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1007 use ObjectListErrorKind::*;
1008 let kind: &str = match &self.kind {
1009 KeyCount(_) => "key-count",
1010 Prefix(_) => "prefix",
1011 CommonPrefix(_) => "common-prefix",
1012 MaxKeys(_) => "max-keys",
1013 #[cfg(test)]
1014 Bar => "bar",
1015 };
1016 write!(f, "parse {kind} failed, gived str: {}", self.source)
1017 }
1018}
1019
1020impl Error for ObjectListError {
1021 fn source(&self) -> Option<&(dyn Error + 'static)> {
1022 use ObjectListErrorKind::*;
1023 match &self.kind {
1024 KeyCount(e) | MaxKeys(e) => Some(e),
1025 Prefix(e) | CommonPrefix(e) => Some(e),
1026 #[cfg(test)]
1027 Bar => None,
1028 }
1029 }
1030}
1031
1032impl ListError for ObjectListError {}
1033
1034#[derive(Debug)]
1036#[non_exhaustive]
1037enum ObjectListErrorKind {
1038 KeyCount(ParseIntError),
1040 Prefix(InvalidObjectDir),
1042 CommonPrefix(InvalidObjectDir),
1044 MaxKeys(ParseIntError),
1046 #[cfg(test)]
1047 Bar,
1048}
1049
1050impl Client {
1051 #[inline(always)]
1057 pub async fn get_object_list<Q: IntoIterator<Item = (QueryKey, QueryValue)>>(
1058 &self,
1059 query: Q,
1060 ) -> Result<ObjectList, ExtractListError> {
1061 self.get_object_list2(Query::from_iter(query)).await
1062 }
1063
1064 pub async fn get_object_list2(&self, query: Query) -> Result<ObjectList, ExtractListError> {
1066 let bucket = BucketBase::new(self.bucket.to_owned(), self.endpoint.to_owned());
1067
1068 let (bucket_url, resource) = bucket.get_url_resource(&query);
1069
1070 let mut list = ObjectList::<ArcPointer> {
1071 object_list: Vec::with_capacity(query.get_max_keys()),
1072 bucket,
1073 ..Default::default()
1074 };
1075
1076 let response = self.builder(Method::GET, bucket_url, resource)?;
1077 let content = response.send_adjust_error().await?;
1078
1079 list.decode(
1080 &content.text().await?,
1081 ObjectList::<ArcPointer>::init_object,
1082 )?;
1083
1084 list.set_client(Arc::new(self.clone()));
1085 list.set_search_query(query);
1086
1087 Ok(list)
1088 }
1089
1090 #[inline]
1173 pub async fn base_object_list<
1174 Q: IntoIterator<Item = (QueryKey, QueryValue)>,
1175 List,
1176 Item,
1177 E: ListError,
1178 ItemErr: Error + 'static,
1179 >(
1180 &self,
1181 query: Q,
1182 list: &mut List,
1183 ) -> Result<(), ExtractListError>
1184 where
1185 List: RefineObjectList<Item, E, ItemErr> + InitObject<Item>,
1186 Item: RefineObject<ItemErr>,
1187 {
1188 let query = Query::from_iter(query);
1189
1190 self.base_object_list2(&query, list).await
1191 }
1192
1193 pub async fn base_object_list2<List, Item, E: ListError, ItemErr: Error + 'static>(
1199 &self,
1200 query: &Query,
1201 list: &mut List,
1202 ) -> Result<(), ExtractListError>
1203 where
1204 List: RefineObjectList<Item, E, ItemErr> + InitObject<Item>,
1205 Item: RefineObject<ItemErr>,
1206 {
1207 let bucket = self.get_bucket_base();
1208 let (bucket_url, resource) = bucket.get_url_resource(query);
1209
1210 let response = self.builder(Method::GET, bucket_url, resource)?;
1211 let content = response.send_adjust_error().await?;
1212
1213 list.decode(&content.text().await?, List::init_object)?;
1214
1215 Ok(())
1216 }
1217
1218 pub async fn get_custom_object<Item, ItemErr>(
1223 &self,
1224 query: &Query,
1225 ) -> Result<Objects<Item>, ExtractListError>
1226 where
1227 Item: RefineObject<ItemErr>,
1228 Objects<Item>: InitObject<Item>,
1229 ItemErr: Error + 'static,
1230 {
1231 let mut list = Objects::<Item>::default();
1232
1233 self.base_object_list2(query, &mut list).await?;
1234
1235 Ok(list)
1236 }
1237}
1238
1239#[derive(Debug)]
1243#[non_exhaustive]
1244pub struct ExtractListError {
1245 pub(crate) kind: ExtractListErrorKind,
1246}
1247
1248impl ExtractListError {
1249 pub fn is_no_more(&self) -> bool {
1251 matches!(self.kind, ExtractListErrorKind::NoMoreFile)
1252 }
1253}
1254
1255#[derive(Debug)]
1259#[non_exhaustive]
1260pub(crate) enum ExtractListErrorKind {
1261 #[doc(hidden)]
1262 Builder(BuilderError),
1263
1264 #[doc(hidden)]
1265 Reqwest(reqwest::Error),
1266
1267 Decode(InnerListError),
1269
1270 NoMoreFile,
1272}
1273
1274impl From<InnerListError> for ExtractListError {
1275 fn from(value: InnerListError) -> Self {
1276 use ExtractListErrorKind::*;
1277 Self {
1278 kind: Decode(value),
1279 }
1280 }
1281}
1282impl From<BuilderError> for ExtractListError {
1283 fn from(value: BuilderError) -> Self {
1284 use ExtractListErrorKind::*;
1285 Self {
1286 kind: Builder(value),
1287 }
1288 }
1289}
1290impl From<reqwest::Error> for ExtractListError {
1291 fn from(value: reqwest::Error) -> Self {
1292 use ExtractListErrorKind::*;
1293 Self {
1294 kind: Reqwest(value),
1295 }
1296 }
1297}
1298impl Display for ExtractListError {
1299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1300 use ExtractListErrorKind::*;
1301 match &self.kind {
1302 Builder(_) => "builder error".fmt(f),
1303 Reqwest(_) => "reqwest error".fmt(f),
1304 Decode(_) => "decode xml failed".fmt(f),
1305 NoMoreFile => "no more file".fmt(f),
1306 }
1307 }
1308}
1309impl Error for ExtractListError {
1310 fn source(&self) -> Option<&(dyn Error + 'static)> {
1311 use ExtractListErrorKind::*;
1312 match &self.kind {
1313 Builder(e) => Some(e),
1314 Reqwest(e) => Some(e),
1315 Decode(e) => e.get_source(),
1316 NoMoreFile => None,
1317 }
1318 }
1319}
1320
1321#[cfg(feature = "blocking")]
1322impl ClientRc {
1323 pub fn get_object_list<Q: IntoIterator<Item = (QueryKey, QueryValue)>>(
1327 self,
1328 query: Q,
1329 ) -> Result<ObjectList<RcPointer>, ExtractListError> {
1330 let query = Query::from_iter(query);
1331
1332 let bucket = BucketBase::new(self.bucket.to_owned(), self.endpoint.to_owned());
1333
1334 let (bucket_url, resource) = bucket.get_url_resource(&query);
1335
1336 let mut list = ObjectList::<RcPointer> {
1337 object_list: Vec::with_capacity(query.get_max_keys()),
1338 bucket,
1339 ..Default::default()
1340 };
1341
1342 let response = self.builder(Method::GET, bucket_url, resource)?;
1343 let content = response.send_adjust_error()?;
1344
1345 list.decode(&content.text()?, ObjectList::<RcPointer>::init_object)?;
1346
1347 list.set_client(Rc::new(self));
1348 list.set_search_query(query);
1349
1350 Ok(list)
1351 }
1352
1353 #[inline]
1355 pub fn base_object_list<
1356 Q: IntoIterator<Item = (QueryKey, QueryValue)>,
1357 List,
1358 Item,
1359 F,
1360 E: ListError,
1361 ItemErr: Error + 'static,
1362 >(
1363 &self,
1364 query: Q,
1365 list: &mut List,
1366 init_object: F,
1367 ) -> Result<(), ExtractListError>
1368 where
1369 List: RefineObjectList<Item, E, ItemErr>,
1370 Item: RefineObject<ItemErr>,
1371 F: Fn(&mut List) -> Option<Item>,
1372 {
1373 let bucket = BucketBase::new(self.bucket.clone(), self.endpoint.to_owned());
1374
1375 let query = Query::from_iter(query);
1376 let (bucket_url, resource) = bucket.get_url_resource(&query);
1377
1378 let response = self.builder(Method::GET, bucket_url, resource)?;
1379 let content = response.send_adjust_error()?;
1380
1381 list.decode(&content.text()?, init_object)?;
1382
1383 Ok(())
1384 }
1385}
1386
1387#[cfg(feature = "blocking")]
1388impl Iterator for ObjectList<RcPointer> {
1389 type Item = ObjectList<RcPointer>;
1390 fn next(&mut self) -> Option<Self> {
1391 if !self.next_continuation_token.is_empty() {
1392 self.search_query
1393 .insert(CONTINUATION_TOKEN, self.next_continuation_token.to_owned());
1394 self.get_object_list().ok()
1395 } else {
1396 None
1397 }
1398 }
1399}
1400
1401#[oss_gen_rc]
1457impl PartialEq<Object<ArcPointer>> for Object<ArcPointer> {
1458 #[inline]
1459 fn eq(&self, other: &Object<ArcPointer>) -> bool {
1460 self.base == other.base
1461 && self.last_modified == other.last_modified
1462 && self.etag == other.etag
1463 && self._type == other._type
1464 && self.size == other.size
1465 && self.storage_class == other.storage_class
1466 }
1467}
1468
1469impl<T: PointerFamily> PartialEq<DateTime<Utc>> for Object<T> {
1470 #[inline]
1471 fn eq(&self, other: &DateTime<Utc>) -> bool {
1472 &self.last_modified == other
1473 }
1474}
1475
1476impl<T: PointerFamily> PartialEq<u64> for Object<T> {
1477 #[inline]
1478 fn eq(&self, other: &u64) -> bool {
1479 &self.size == other
1480 }
1481}
1482
1483#[oss_gen_rc]
1484impl PartialEq<ObjectBase<ArcPointer>> for Object<ArcPointer> {
1485 #[inline]
1486 fn eq(&self, other: &ObjectBase<ArcPointer>) -> bool {
1487 &self.base == other
1488 }
1489}
1490
1491#[derive(Default)]
1493#[doc(hidden)]
1494pub struct PutObject<'a> {
1495 pub forbid_overwrite: bool,
1496 pub server_side_encryption: Option<Encryption>,
1497 pub server_side_data_encryption: Option<Encryption>,
1498 pub server_side_encryption_key_id: Option<&'a str>,
1499 pub object_acl: ObjectAcl,
1500 pub storage_class: StorageClass,
1501 pub tagging: Option<&'a str>,
1502}
1503
1504#[derive(Default)]
1506#[doc(hidden)]
1507pub enum Encryption {
1508 #[default]
1509 Aes256,
1510 Kms,
1511 Sm4,
1512}
1513
1514#[derive(Default)]
1516#[doc(hidden)]
1517pub enum ObjectAcl {
1518 #[default]
1519 Default,
1520 Private,
1521 PublicRead,
1522 PublicReadWrite,
1523}
1524
1525#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
1527#[non_exhaustive]
1528pub struct StorageClass {
1529 kind: StorageClassKind,
1530}
1531
1532#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
1533#[non_exhaustive]
1534enum StorageClassKind {
1535 #[default]
1537 Standard,
1538 IA,
1540 Archive,
1542 ColdArchive,
1544}
1545
1546impl StorageClass {
1547 pub const ARCHIVE: Self = Self {
1549 kind: StorageClassKind::Archive,
1550 };
1551 pub const IA: Self = Self {
1553 kind: StorageClassKind::IA,
1554 };
1555 pub const STANDARD: Self = Self {
1557 kind: StorageClassKind::Standard,
1558 };
1559 pub const COLD_ARCHIVE: Self = Self {
1561 kind: StorageClassKind::ColdArchive,
1562 };
1563
1564 pub fn new(s: &str) -> Option<StorageClass> {
1566 let start_char = s.chars().next()?;
1567
1568 let kind = match start_char {
1569 'a' | 'A' => StorageClassKind::Archive,
1570 'i' | 'I' => StorageClassKind::IA,
1571 's' | 'S' => StorageClassKind::Standard,
1572 'c' | 'C' => StorageClassKind::ColdArchive,
1573 _ => return None,
1574 };
1575 Some(Self { kind })
1576 }
1577}
1578
1579#[derive(Default)]
1581#[doc(hidden)]
1582pub struct CopyObject<'a> {
1583 pub forbid_overwrite: bool,
1584 pub copy_source: &'a str,
1585 pub copy_source_if_match: Option<&'a str>,
1586 pub copy_source_if_none_match: Option<&'a str>,
1587 pub copy_source_if_unmodified_since: Option<&'a str>,
1588 pub copy_source_if_modified_since: Option<&'a str>,
1589 pub metadata_directive: CopyDirective,
1590 pub server_side_encryption: Option<Encryption>,
1591 pub server_side_encryption_key_id: Option<&'a str>,
1592 pub object_acl: ObjectAcl,
1593 pub storage_class: StorageClass,
1594 pub tagging: Option<&'a str>,
1595 pub tagging_directive: CopyDirective,
1596}
1597
1598#[derive(Default)]
1600#[doc(hidden)]
1601pub enum CopyDirective {
1602 #[default]
1603 Copy,
1604 Replace,
1605}