1use serde::{
2 de::{self, MapAccess, Visitor},
3 ser::SerializeMap,
4 Deserialize, Deserializer, Serialize, Serializer,
5};
6use std::{collections::HashMap, fmt};
7use strum_macros::Display;
8
9use crate::util::B2FileStream;
10
11#[derive(Debug, Display, Clone, PartialEq, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13#[strum(serialize_all = "snake_case")]
14pub enum B2Endpoint {
15 B2AuthorizeAccount,
16 B2CancelLargeFile,
17 B2CopyFile,
18 B2CopyPart,
19 B2CreateBucket,
20 B2CreateKey,
21 B2DeleteBucket,
22 B2DeleteFileVersion,
23 B2DeleteKey,
24 B2DownloadFileById,
25 B2DownloadFileByName,
26 B2FinishLargeFile,
27 B2GetBucketNotificationRules,
28 B2GetDownloadAuthorization,
29 B2GetFileInfo,
30 B2GetUploadPartUrl,
31 B2GetUploadUrl,
32 B2HideFile,
33 B2ListBuckets,
34 B2ListFileNames,
35 B2ListFileVersions,
36 B2ListKeys,
37 B2ListParts,
38 B2ListUnfinishedLargeFiles,
39 B2SetBucketNotificationRules,
40 B2StartLargeFile,
41 B2UpdateBucket,
42 B2UpdateFileLegalHold,
43 B2UpdateFileRetention,
44 B2UploadFile,
45 B2UploadPart,
46}
47
48#[derive(Debug, Display, Clone, PartialEq, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub enum B2KeyCapability {
51 ListKeys,
52 WriteKeys,
53 DeleteKeys,
54 ListBuckets,
55 ListAllBucketNames,
56 ReadBuckets,
57 WriteBuckets,
58 DeleteBuckets,
59 ReadBucketRetentions,
60 WriteBucketRetentions,
61 ReadBucketEncryption,
62 WriteBucketEncryption,
63 ListFiles,
64 ReadFiles,
65 ShareFiles,
66 WriteFiles,
67 DeleteFiles,
68 ReadFileLegalHolds,
69 WriteFileLegalHolds,
70 ReadFileRetentions,
71 WriteFileRetentions,
72 BypassGovernance,
73 ReadBucketReplications,
74 WriteBucketReplications,
75 WriteBucketNotifications,
76 ReadBucketNotifications,
77 ReadBucketLogging,
78 WriteBucketLogging,
79}
80
81#[derive(Debug, Display, Clone, PartialEq, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub enum B2Action {
84 Upload,
86 Start,
88 Hide,
90 Folder,
92}
93
94#[derive(Clone, Deserialize, Serialize, Debug)]
95#[serde(rename_all = "camelCase")]
96pub struct B2LifeCycleRules {
97 pub days_from_hiding_to_deleting: Option<u32>,
98 pub days_from_uploading_to_hiding: Option<u32>,
99 pub file_name_prefix: Box<str>,
100}
101
102#[derive(Clone, Deserialize, Debug, Serialize)]
106#[serde(rename_all = "lowercase")]
107pub enum B2ReplicationStatus {
108 Pending,
109 Completed,
110 Failed,
111 Replica,
112}
113
114#[derive(Clone, Debug)]
122pub enum B2ServerSideEncryption {
123 Disabled,
125 SseB2 {
126 algorithm: B2ServerSideEncryptionAlgorithm,
127 },
128 SseC {
129 algorithm: B2ServerSideEncryptionAlgorithm,
130 customer_key: String,
131 customer_key_md5: String,
132 },
133}
134
135impl Serialize for B2ServerSideEncryption {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: Serializer,
139 {
140 use B2ServerSideEncryption::*;
141
142 match self {
143 Disabled => {
144 let mut map = serializer.serialize_map(Some(1))?;
145 map.serialize_entry("mode", &Option::<String>::None)?;
146 map.end()
147 }
148 SseB2 { algorithm } => {
149 let mut map = serializer.serialize_map(Some(2))?;
150 map.serialize_entry("mode", "SSE-B2")?;
151 map.serialize_entry("algorithm", algorithm)?;
152 map.end()
153 }
154 SseC {
155 algorithm,
156 customer_key,
157 customer_key_md5,
158 } => {
159 let mut map = serializer.serialize_map(Some(4))?;
160 map.serialize_entry("mode", "SSE-C")?;
161 map.serialize_entry("algorithm", algorithm)?;
162 map.serialize_entry("customerKey", customer_key)?;
163 map.serialize_entry("customerKeyMd5", customer_key_md5)?;
164 map.end()
165 }
166 }
167 }
168}
169
170impl<'de> Deserialize<'de> for B2ServerSideEncryption {
171 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
172 where
173 D: Deserializer<'de>,
174 {
175 struct B2ServerSideEncryptionVisitor;
176
177 impl<'de> Visitor<'de> for B2ServerSideEncryptionVisitor {
178 type Value = B2ServerSideEncryption;
179
180 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
181 formatter.write_str("a B2ServerSideEncryption object")
182 }
183
184 fn visit_map<M>(self, mut map: M) -> Result<B2ServerSideEncryption, M::Error>
185 where
186 M: MapAccess<'de>,
187 {
188 let mut mode: Option<String> = None;
189 let mut algorithm = None;
190 let mut customer_key = None;
191 let mut customer_key_md5 = None;
192
193 while let Some(key) = map.next_key()? {
194 match key {
195 "mode" => mode = map.next_value()?,
196 "algorithm" => algorithm = map.next_value()?,
197 "customerKey" => customer_key = map.next_value()?,
198 "customerKeyMd5" => customer_key_md5 = map.next_value()?,
199 _ => continue,
200 }
201 }
202
203 match mode {
204 Some(mode_str) => match mode_str.as_str() {
205 "SSE-B2" => {
206 let algorithm =
207 algorithm.ok_or_else(|| de::Error::missing_field("algorithm"))?;
208 Ok(B2ServerSideEncryption::SseB2 { algorithm })
209 }
210 "SSE-C" => {
211 let algorithm =
212 algorithm.ok_or_else(|| de::Error::missing_field("algorithm"))?;
213 let customer_key = customer_key
214 .ok_or_else(|| de::Error::missing_field("customerKey"))?;
215 let customer_key_md5 = customer_key_md5
216 .ok_or_else(|| de::Error::missing_field("customerKeyMd5"))?;
217 Ok(B2ServerSideEncryption::SseC {
218 algorithm,
219 customer_key,
220 customer_key_md5,
221 })
222 }
223 _ => Err(de::Error::unknown_variant(
224 mode_str.as_str(),
225 &["SSE-B2", "SSE-C"],
226 )),
227 },
228 None => Ok(B2ServerSideEncryption::Disabled),
229 }
230 }
231 }
232
233 deserializer.deserialize_map(B2ServerSideEncryptionVisitor)
234 }
235}
236
237#[derive(Clone, Deserialize, Debug, Serialize)]
238#[serde(rename_all = "camelCase")]
239pub struct B2FileRetentionPeriod {
240 pub duration: u64,
241 pub unit: String,
242}
243
244pub struct B2DownloadFileContent {
245 pub file: B2FileStream,
246 pub file_details: B2FileDownloadDetails,
247 pub remaining_headers: HashMap<String, String>,
248}
249
250#[derive(Clone, Deserialize, Serialize, Debug)]
251#[serde(rename_all = "camelCase")]
252pub struct B2BucketRetention {
253 pub mode: Option<String>,
254 #[serde(skip_serializing_if = "Option::is_none")]
255 pub period: Option<B2FileRetentionPeriod>,
256}
257
258#[derive(Clone, Deserialize, Debug, Serialize)]
259#[serde(rename_all = "camelCase")]
260pub struct B2ObjectLockValue {
261 pub default_retention: B2BucketRetention,
262 pub is_file_lock_enabled: bool,
263}
264
265#[derive(Clone, Deserialize, Debug, Serialize)]
266#[serde(rename_all = "camelCase")]
267pub struct B2BucketFileRetention {
268 pub mode: Option<B2FileRetentionMode>,
270 pub retain_until_timestamp: Option<u64>,
272}
273
274#[derive(Clone, Deserialize, Debug, Serialize)]
275#[serde(rename_all = "camelCase")]
276pub struct B2ObjectLock<T> {
277 pub is_client_authorized_to_read: bool,
278 pub value: Option<T>,
279}
280
281#[derive(Clone, Deserialize, Debug, Serialize)]
282#[serde(rename_all = "camelCase")]
283pub enum B2FileAction {
284 Start,
285 Upload,
286 Hide,
287 Folder,
288}
289
290#[derive(Clone, Deserialize, Debug, Serialize)]
291#[serde(rename_all = "camelCase")]
292pub struct B2File {
293 pub account_id: String,
295 pub action: B2Action,
297 pub bucket_id: String,
299 pub content_length: u64,
302 pub content_sha1: Option<String>,
305 pub content_md5: Option<String>,
309 pub content_type: Option<String>,
312 pub file_id: String,
316 pub file_info: HashMap<String, String>,
318 pub file_name: String,
320 pub file_retention: Option<B2ObjectLock<B2BucketFileRetention>>,
325 pub legal_hold: Option<B2ObjectLock<B2FileLegalHold>>,
330 pub replication_status: Option<B2ReplicationStatus>,
332 pub server_side_encryption: Option<B2ServerSideEncryption>,
337 pub upload_timestamp: u64,
344}
345
346#[derive(Clone, Deserialize, Serialize, Debug)]
347pub enum B2ServerSideEncryptionAlgorithm {
348 AES256,
349}
350
351#[derive(Clone, Deserialize, Serialize, Debug)]
352#[serde(rename_all = "camelCase")]
353pub enum B2FileRetentionMode {
354 Governance,
355 Compliance,
356}
357
358#[derive(Clone, Serialize, Debug, Deserialize)]
359#[serde(rename_all = "camelCase")]
360pub enum B2FileLegalHold {
361 On,
362 Off,
363}
364
365#[derive(Clone, Serialize, Debug, Deserialize)]
366#[serde(rename_all = "camelCase")]
367pub enum B2BucketType {
368 AllPublic,
370 AllPrivate,
372 Restricted,
373 Snapshot,
375 Shared,
376}
377
378#[derive(Clone, Serialize, Debug, Deserialize)]
379#[serde(rename_all = "camelCase")]
380pub enum B2BucketTypeUpdate {
381 AllPublic,
383 AllPrivate,
385}
386
387#[derive(Clone, Serialize, Debug, Deserialize)]
388#[serde(rename_all = "camelCase")]
389pub struct B2CorsRule {
390 pub cors_rule_name: String,
391 pub allowed_origins: Vec<String>,
392 pub allowed_operations: Vec<B2Endpoint>,
393 pub expose_headers: Vec<String>,
394 pub max_age_seconds: u32,
395}
396
397#[derive(Clone, Serialize, Debug, Deserialize)]
398#[serde(rename_all = "camelCase")]
399pub struct B2ReplicationRule {
400 pub destination_bucket_id: String,
401 pub file_name_prefix: String,
402 pub include_existing_files: bool,
403 pub is_enabled: bool,
404 pub priority: u16,
405 pub replication_rule_name: String,
406}
407
408#[derive(Clone, Serialize, Debug, Deserialize)]
409#[serde(rename_all = "camelCase")]
410pub enum B2ReplicationConfig {
411 #[serde(rename_all = "camelCase")]
412 AsReplicationSource {
413 replication_rules: Vec<B2ReplicationRule>,
414 source_application_key_id: String,
415 },
416 #[serde(rename_all = "camelCase")]
417 AsReplicationDestination {
418 source_application_key_id: HashMap<String, String>,
419 },
420}
421
422#[derive(Clone, Serialize, Debug, Deserialize)]
423#[serde(rename_all = "camelCase")]
424pub enum B2BucketOption {
426 S3,
427 #[serde(untagged)]
428 Unknown(String),
429}
430
431#[derive(Clone, Serialize, Debug, Deserialize)]
432pub enum B2EventNotificationEventType {
434 #[serde(rename = "b2:ObjectCreated:Upload")]
437 ObjectCreatedUpload,
438 #[serde(rename = "b2:ObjectCreated:MultipartUpload")]
441 ObjectCreatedMultipartUpload,
442 #[serde(rename = "b2:ObjectCreated:Copy")]
445 ObjectCreatedCopy,
446 #[serde(rename = "b2:ObjectCreated:Replica")]
449 ObjectCreatedReplica,
450 #[serde(rename = "b2:ObjectCreated:MultipartReplica")]
453 ObjectMultipartReplica,
454 #[serde(rename = "b2:ObjectCreated:*")]
457 ObjectCreatedAll,
458 #[serde(rename = "b2:ObjectDeleted:Delete")]
461 ObjectDeleted,
462 #[serde(rename = "b2:ObjectDeleted:LifecycleRule")]
465 ObjectDeletedLifecycle,
466 #[serde(rename = "b2:ObjectDeleted:*")]
469 ObjectDeletedAll,
470 #[serde(rename = "b2:HideMarkerCreated:Hide")]
473 HideMarkerCreated,
474 #[serde(rename = "b2:HideMarkerCreated:LifecycleRule")]
477 HideMarkerCreatedLifeCycle,
478 #[serde(rename = "b2:HideMarkerCreated:*")]
481 HideMarkerAll,
482 #[serde(rename = "b2:MultipartUploadCreated:LiveRead")]
485 MultiPartUploadCreatedLiveRead,
486 #[serde(rename = "b2:MultipartUploadCreated:*")]
489 MultiPartUploadCreatedAll,
490}
491
492#[derive(Clone, Serialize, Debug, Deserialize)]
493#[serde(rename_all = "camelCase")]
494pub enum B2EventNotificationTargetType {
495 Webhook,
496}
497
498#[derive(Clone, Serialize, Debug, Deserialize)]
499#[serde(rename_all = "camelCase")]
500pub struct B2EventNotificationRule {
501 pub event_types: Vec<B2EventNotificationEventType>,
503 pub is_enabled: bool,
505 pub name: String,
507 pub object_name_prefix: String,
509 pub is_suspended: Option<bool>,
511 pub max_events_per_batch: Option<u8>,
513 pub suspension_reason: Option<String>,
515 pub target_configuration: B2NotificationConfiguration,
519}
520
521#[derive(Clone, Serialize, Debug, Deserialize)]
522#[serde(rename_all = "camelCase")]
523pub struct B2NotificationConfiguration {
524 pub url: String,
526 pub target_type: B2EventNotificationTargetType,
528 pub hmac_sha256_signing_secret: Option<String>,
530 pub custom_headers: Option<HashMap<String, String>>,
532}
533
534#[derive(Clone, Serialize, Debug, Deserialize)]
535#[serde(rename_all = "camelCase")]
536pub struct B2FilePart {
537 pub file_id: String,
538 pub part_number: u32,
539 pub content_length: u64,
540 pub content_sha1: String,
541 pub content_md5: Option<String>,
542 pub server_side_encryption: B2ServerSideEncryption,
543 pub upload_timestamp: u64,
544}
545
546#[derive(Clone, Serialize, Debug, Deserialize)]
547#[serde(rename_all = "camelCase")]
548pub struct B2AppKey {
549 pub account_id: String,
551 pub application_key_id: String,
553 pub application_key: Option<String>,
555 pub bucket_id: Option<String>,
557 pub capabilities: Vec<B2KeyCapability>,
559 pub expiration_timestamp: Option<u64>,
561 pub key_name: String,
563 pub name_prefix: Option<String>,
565 pub options: Option<Vec<B2BucketOption>>,
567}
568
569#[derive(Clone, Debug, Deserialize)]
570#[serde(rename_all = "camelCase")]
571pub struct B2Bucket {
572 pub account_id: String,
574 pub bucket_id: String,
576 pub bucket_name: String,
578 pub bucket_type: B2BucketType,
580 pub bucket_info: HashMap<String, String>,
582 pub cors_rules: Vec<B2CorsRule>,
585 pub file_lock_configuration: B2ObjectLock<B2BucketFileRetention>,
589 pub default_server_side_encryption: B2ServerSideEncryption,
593 pub life_cycle_rules: Option<Vec<B2LifeCycleRules>>,
596 pub replication_configuration: B2ReplicationConfig,
601 pub revision: u32,
604 pub options: Option<Vec<B2BucketOption>>,
606}
607
608#[derive(Clone, Debug, Deserialize, Serialize)]
609#[serde(rename_all = "camelCase")]
610pub struct B2CustomerAgnosticServerSideEncryption {
611 pub customer_key: String,
612 pub customer_key_md5: String,
613 #[serde(flatten)]
614 pub server_side_encryption: B2ServerSideEncryption,
615}
616
617#[derive(Clone, Debug, Deserialize, Serialize)]
618#[serde(rename_all = "UPPERCASE")]
619pub enum B2MetadataDirective {
620 Copy,
621}
622
623#[derive(Clone, Debug, Deserialize, Serialize)]
624#[serde(rename_all = "camelCase")]
625pub struct B2FileDownloadDetails {
626 pub content_length: u64,
627 pub content_type: String,
628 pub file_id: String,
629 pub file_name: String,
630 pub content_sha1: Option<String>,
631 pub upload_timestamp: u64,
632 pub file_info: Option<HashMap<String, String>>,
633}