1use super::{acl::AccessControlList, object::Object, oss, DataRedundancyType, StorageClass};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Serialize, Default, Clone)]
5pub struct CreateBucketConfiguration {
6 #[serde(rename = "StorageClass", skip_serializing_if = "Option::is_none")]
7 pub storage_class: Option<StorageClass>,
8 #[serde(
9 rename = "data_redundancy_type",
10 skip_serializing_if = "Option::is_none"
11 )]
12 pub data_redundancy_type: Option<DataRedundancyType>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, Default)]
16pub struct Owner {
17 #[serde(rename = "ID")]
18 pub id: String,
19 #[serde(rename = "DisplayName")]
20 pub display_name: String,
21}
22
23#[derive(Debug, Serialize, Deserialize, Clone)]
25#[serde(rename = "$value")]
26pub struct LocationConstraint(pub String);
27
28#[derive(Debug, Serialize, Deserialize, Default, Clone)]
29pub struct BucketPolicy {
30 #[serde(rename(deserialize = "LogBucket"))]
31 pub log_bucket: String,
32 #[serde(rename(deserialize = "LogPrefix"))]
33 pub log_prefix: String,
34}
35
36#[derive(Debug, Serialize, Deserialize, Default, Clone)]
37pub struct Bucket {
38 #[serde(rename = "AccessMonitor")]
39 pub access_monitor: Option<String>,
40 #[serde(rename = "CreationDate")]
41 pub creation_date: String,
42 #[serde(rename = "ExtranetEndpoint")]
43 pub extranet_endpoint: String,
44 #[serde(rename = "IntranetEndpoint")]
45 pub intranet_endpoint: String,
46 #[serde(rename = "Location")]
47 pub location: String,
48 #[serde(rename = "StorageClass")]
49 pub storage_class: StorageClass,
50 #[serde(rename = "TransferAcceleration")]
51 pub transfer_acceleration: Option<String>,
52 #[serde(rename = "CrossRegionReplication")]
53 pub cross_region_replication: Option<String>,
54 #[serde(rename = "Name")]
55 pub name: String,
56 #[serde(rename = "ResourceGroupId")]
57 pub resource_group_id: Option<String>,
58 #[serde(rename = "Owner")]
59 pub owner: Option<Owner>,
60 #[serde(rename = "AccessControlList")]
61 pub access_control_list: Option<AccessControlList>,
62 #[serde(rename = "Comment")]
63 pub comment: Option<String>,
64 #[serde(rename = "BucketPolicy")]
65 pub bucket_policy: Option<BucketPolicy>,
66}
67
68#[derive(Debug, Serialize, Deserialize, Default, Clone)]
69pub struct BucketInfo {
70 #[serde(rename(deserialize = "Bucket"))]
71 pub bucket: Bucket,
72}
73
74#[derive(Debug, Serialize, Deserialize, Default, Clone)]
75pub struct Buckets {
76 #[serde(rename(deserialize = "Bucket"))]
77 pub bucket: Option<Vec<Bucket>>,
78}
79
80#[derive(Debug, Serialize, Deserialize, Default, Clone)]
81pub struct ListAllMyBucketsResult {
82 #[serde(rename(deserialize = "Owner"))]
83 pub owner: Owner,
84 #[serde(rename(deserialize = "Buckets"))]
85 pub buckets: Buckets,
86}
87
88impl From<oss::Bytes> for ListAllMyBucketsResult {
89 fn from(data: oss::Bytes) -> Self {
90 let content = String::from_utf8_lossy(&data);
91 quick_xml::de::from_str::<Self>(&content).unwrap()
92 }
93}
94
95#[derive(Debug, Default, Serialize, Deserialize, Clone)]
96pub struct BucketStat {
97 #[serde(rename(deserialize = "Storage"))]
99 pub storage: u64,
100 #[serde(rename(deserialize = "ObjectCount"))]
102 pub object_count: u64,
103 #[serde(rename(deserialize = "MultipartUploadCount"))]
104 pub multipart_upload_count: u64,
105 #[serde(rename(deserialize = "LiveChannelCount"))]
106 pub live_channel_count: u64,
107 #[serde(rename(deserialize = "LastModifiedTime"))]
108 pub last_modified_time: u64,
109 #[serde(rename(deserialize = "StandardStorage"))]
110 pub standard_storage: u64,
111 #[serde(rename(deserialize = "StandardObjectCount"))]
112 pub standard_object_count: u64,
113 #[serde(rename(deserialize = "InfrequentAccessStorage"))]
114 pub infrequent_access_storage: u64,
115 #[serde(rename(deserialize = "InfrequentAccessRealStorage"))]
116 pub infrequent_access_real_storage: u64,
117 #[serde(rename(deserialize = "InfrequentAccessObjectCount"))]
118 pub infrequent_access_object_count: u64,
119 #[serde(rename(deserialize = "ArchiveStorage"))]
120 pub archive_storage: u64,
121 #[serde(rename(deserialize = "ArchiveRealStorage"))]
122 pub archive_real_storage: u64,
123 #[serde(rename(deserialize = "ArchiveObjectCount"))]
124 pub archive_object_count: u64,
125 #[serde(rename(deserialize = "ColdArchiveStorage"))]
126 pub cold_archive_storage: u64,
127 #[serde(rename(deserialize = "ColdArchiveRealStorage"))]
128 pub cold_archive_real_storage: u64,
129 #[serde(rename(deserialize = "ColdArchiveObjectCount"))]
130 pub cold_archive_object_count: u64,
131}
132
133#[derive(Debug, Serialize, Deserialize, Clone)]
134pub struct ListBucketResult2 {
135 #[serde(rename = "Name")]
136 pub name: String,
137 #[serde(rename = "Prefix")]
138 pub prefix: String,
139 #[serde(rename = "MaxKeys")]
140 pub max_keys: i32,
141 #[serde(rename = "EncodingType")]
142 pub encoding_type: Option<String>,
143 #[serde(rename = "IsTruncated")]
144 pub is_truncated: bool,
145 #[serde(rename = "KeyCount")]
146 pub key_count: Option<u32>,
147 #[serde(rename = "NextContinuationToken")]
148 pub next_continuation_token: Option<String>,
149 #[serde(rename = "Contents")]
150 pub contents: Option<Vec<Object>>,
151 #[serde(rename = "CommonPrefixes")]
152 pub common_prefixes: Option<Vec<CommonPrefixes>>
153}
154
155#[derive(Debug, Serialize, Deserialize, Clone, Default)]
156pub struct CommonPrefixes {
157 #[serde(rename = "Prefix")]
158 pub prefix: String,
159}
160
161#[derive(Debug, Serialize, Deserialize, Clone)]
162pub struct Contents {
163 #[serde(rename = "Key")]
164 pub key: String,
165 #[serde(rename = "LastModified")]
166 pub last_modified: String,
167 #[serde(rename = "ETag")]
168 pub etag: String,
169 #[serde(rename = "Type")]
170 pub r#type: String,
171 #[serde(rename = "Size")]
172 pub size: i32,
173 #[serde(rename = "StorageClass")]
174 pub storage_class: StorageClass,
175 #[serde(rename = "Owner")]
176 pub owner: Option<Owner>,
177}
178
179#[derive(Debug, Serialize, Deserialize, Clone)]
180pub struct ListBucketResult {
181 #[serde(rename = "Name")]
182 pub name: String,
183 #[serde(rename = "Prefix")]
184 pub prefix: String,
185 #[serde(rename = "Marker")]
186 pub marker: String,
187 #[serde(rename = "MaxKeys")]
188 pub max_keys: i32,
189 #[serde(rename = "Delimiter")]
190 pub delimiter: String,
191 #[serde(rename = "IsTruncated")]
192 pub is_truncated: bool,
193 #[serde(rename = "NextMarker")]
194 pub next_marker: Option<String>,
195 #[serde(rename = "Contents")]
196 pub contents: Option<Vec<Contents>>,
197 #[serde(rename = "CommonPrefixes")]
198 pub common_prefixes: Option<Vec<CommonPrefixes>>,
199}
200
201#[cfg(test)]
202pub mod test {
203
204 use super::*;
205
206 #[test]
207 fn bucket() {
208 let xml = r#"
210<ListAllMyBucketsResult>
211<Owner>
212 <ID>512**</ID>
213 <DisplayName>51264</DisplayName>
214</Owner>
215<Buckets>
216 <Bucket>
217 <CreationDate>2014-02-17T18:12:43.000Z</CreationDate>
218 <ExtranetEndpoint>oss-cn-shanghai.aliyuncs.com</ExtranetEndpoint>
219 <IntranetEndpoint>oss-cn-shanghai-internal.aliyuncs.com</IntranetEndpoint>
220 <Location>oss-cn-shanghai</Location>
221 <Name>app-base-oss</Name>
222 <Region>cn-shanghai</Region>
223 <StorageClass>Standard</StorageClass>
224 </Bucket>
225 <Bucket>
226 <CreationDate>2014-02-25T11:21:04.000Z</CreationDate>
227 <ExtranetEndpoint>oss-cn-hangzhou.aliyuncs.com</ExtranetEndpoint>
228 <IntranetEndpoint>oss-cn-hangzhou-internal.aliyuncs.com</IntranetEndpoint>
229 <Location>oss-cn-hangzhou</Location>
230 <Name>mybucket</Name>
231 <Region>cn-hangzhou</Region>
232 <StorageClass>IA</StorageClass>
233 </Bucket>
234</Buckets>
235</ListAllMyBucketsResult>
236"#;
237 let obj: ListAllMyBucketsResult = quick_xml::de::from_str(xml).unwrap();
238 let left = "2014-02-17T18:12:43.000Z";
239 let right = &obj.buckets.bucket.unwrap()[0].creation_date;
240 assert_eq!(left, right);
241 }
242
243 #[test]
244 pub fn list_object_v2() {
245 let xml_content = r#"<?xml version="1.0" encoding="UTF-8"?>
246 <ListBucketResult>
247 <Name>xtoss-ex11</Name>
248 <Prefix></Prefix>
249 <MaxKeys>5</MaxKeys>
250 <Delimiter></Delimiter>
251 <IsTruncated>true</IsTruncated>
252 <NextContinuationToken>ChlpbWFnZXMvSlBHSW1hZ2VfMm1ibWIuanBnEAA-</NextContinuationToken>
253 <Contents>
254 <Key>excel/Spreadsheet-1000-rows.xls</Key>
255 <LastModified>2024-02-09T12:11:40.000Z</LastModified>
256 <ETag>"B6DF06A19E3A3AF4F39EBD2E14C64F28"</ETag>
257 <Type>Normal</Type>
258 <Size>217088</Size>
259 <StorageClass>Standard</StorageClass>
260 </Contents>
261 <Contents>
262 <Key>excel/Spreadsheet-5000-rows.xls</Key>
263 <LastModified>2024-02-09T12:11:39.000Z</LastModified>
264 <ETag>"F97C47A00070BC0B945268A26FC8C14A"</ETag>
265 <Type>Normal</Type>
266 <Size>925696</Size>
267 <StorageClass>Standard</StorageClass>
268 </Contents>
269 <Contents>
270 <Key>images/JPGImage_100kbmb.jpg</Key>
271 <LastModified>2024-02-09T12:11:39.000Z</LastModified>
272 <ETag>"12EA14D362611F6CCAB9C66CA0A3FAEF"</ETag>
273 <Type>Normal</Type>
274 <Size>102796</Size>
275 <StorageClass>Standard</StorageClass>
276 </Contents>
277 <Contents>
278 <Key>images/JPGImage_15mbmb.jpg</Key>
279 <LastModified>2024-02-09T12:11:31.000Z</LastModified>
280 <ETag>"AD9D4461988B2D82D53F0DA31CAFEAA5"</ETag>
281 <Type>Normal</Type>
282 <Size>15882755</Size>
283 <StorageClass>Standard</StorageClass>
284 </Contents>
285 <Contents>
286 <Key>images/JPGImage_2mbmb.jpg</Key>
287 <LastModified>2024-02-09T12:11:39.000Z</LastModified>
288 <ETag>"EA5EFC10C2873F1713FDB368E4D25DD7"</ETag>
289 <Type>Normal</Type>
290 <Size>2101546</Size>
291 <StorageClass>Standard</StorageClass>
292 </Contents>
293 <KeyCount>5</KeyCount>
294 </ListBucketResult>"#;
295
296 let entity: ListBucketResult2 = quick_xml::de::from_str(&xml_content).unwrap();
297 let left = "excel/Spreadsheet-1000-rows.xls";
298 let right = &entity.contents.unwrap()[0].key;
299 assert_eq!(&left, &right);
300 }
301}