opendal/raw/
ops.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Ops provides the operation args struct like [`OpRead`] for user.
19//!
20//! By using ops, users can add more context for operation.
21
22use crate::raw::*;
23use chrono::{DateTime, Utc};
24use std::collections::HashMap;
25use std::time::Duration;
26
27/// Args for `create` operation.
28///
29/// The path must be normalized.
30#[derive(Debug, Clone, Default)]
31pub struct OpCreateDir {}
32
33impl OpCreateDir {
34    /// Create a new `OpCreateDir`.
35    pub fn new() -> Self {
36        Self::default()
37    }
38}
39
40/// Args for `delete` operation.
41///
42/// The path must be normalized.
43#[derive(Debug, Clone, Default, Eq, Hash, PartialEq)]
44pub struct OpDelete {
45    version: Option<String>,
46}
47
48impl OpDelete {
49    /// Create a new `OpDelete`.
50    pub fn new() -> Self {
51        Self::default()
52    }
53}
54
55impl OpDelete {
56    /// Change the version of this delete operation.
57    pub fn with_version(mut self, version: &str) -> Self {
58        self.version = Some(version.into());
59        self
60    }
61
62    /// Get the version of this delete operation.
63    pub fn version(&self) -> Option<&str> {
64        self.version.as_deref()
65    }
66}
67
68/// Args for `delete` operation.
69///
70/// The path must be normalized.
71#[derive(Debug, Clone, Default)]
72pub struct OpDeleter {}
73
74impl OpDeleter {
75    /// Create a new `OpDelete`.
76    pub fn new() -> Self {
77        Self::default()
78    }
79}
80
81/// Args for `list` operation.
82#[derive(Debug, Clone)]
83pub struct OpList {
84    /// The limit passed to underlying service to specify the max results
85    /// that could return per-request.
86    ///
87    /// Users could use this to control the memory usage of list operation.
88    limit: Option<usize>,
89    /// The start_after passes to underlying service to specify the specified key
90    /// to start listing from.
91    start_after: Option<String>,
92    /// The recursive is used to control whether the list operation is recursive.
93    ///
94    /// - If `false`, list operation will only list the entries under the given path.
95    /// - If `true`, list operation will list all entries that starts with given path.
96    ///
97    /// Default to `false`.
98    recursive: bool,
99    /// The concurrent of stat operations inside list operation.
100    /// Users could use this to control the number of concurrent stat operation when metadata is unknown.
101    ///
102    /// - If this is set to <= 1, the list operation will be sequential.
103    /// - If this is set to > 1, the list operation will be concurrent,
104    ///   and the maximum number of concurrent operations will be determined by this value.
105    concurrent: usize,
106    /// The version is used to control whether the object versions should be returned.
107    ///
108    /// - If `false`, list operation will not return with object versions
109    /// - If `true`, list operation will return with object versions if object versioning is supported
110    ///   by the underlying service
111    ///
112    /// Default to `false`
113    versions: bool,
114    /// The deleted is used to control whether the deleted objects should be returned.
115    ///
116    /// - If `false`, list operation will not return with deleted objects
117    /// - If `true`, list operation will return with deleted objects if object versioning is supported
118    ///   by the underlying service
119    ///
120    /// Default to `false`
121    deleted: bool,
122}
123
124impl Default for OpList {
125    fn default() -> Self {
126        OpList {
127            limit: None,
128            start_after: None,
129            recursive: false,
130            concurrent: 1,
131            versions: false,
132            deleted: false,
133        }
134    }
135}
136
137impl OpList {
138    /// Create a new `OpList`.
139    pub fn new() -> Self {
140        Self::default()
141    }
142
143    /// Change the limit of this list operation.
144    pub fn with_limit(mut self, limit: usize) -> Self {
145        self.limit = Some(limit);
146        self
147    }
148
149    /// Get the limit of list operation.
150    pub fn limit(&self) -> Option<usize> {
151        self.limit
152    }
153
154    /// Change the start_after of this list operation.
155    pub fn with_start_after(mut self, start_after: &str) -> Self {
156        self.start_after = Some(start_after.into());
157        self
158    }
159
160    /// Get the start_after of list operation.
161    pub fn start_after(&self) -> Option<&str> {
162        self.start_after.as_deref()
163    }
164
165    /// The recursive is used to control whether the list operation is recursive.
166    ///
167    /// - If `false`, list operation will only list the entries under the given path.
168    /// - If `true`, list operation will list all entries that starts with given path.
169    ///
170    /// Default to `false`.
171    pub fn with_recursive(mut self, recursive: bool) -> Self {
172        self.recursive = recursive;
173        self
174    }
175
176    /// Get the current recursive.
177    pub fn recursive(&self) -> bool {
178        self.recursive
179    }
180
181    /// Change the concurrent of this list operation.
182    ///
183    /// The default concurrent is 1.
184    pub fn with_concurrent(mut self, concurrent: usize) -> Self {
185        self.concurrent = concurrent;
186        self
187    }
188
189    /// Get the concurrent of list operation.
190    pub fn concurrent(&self) -> usize {
191        self.concurrent
192    }
193
194    /// Change the version of this list operation
195    #[deprecated(since = "0.51.1", note = "use with_versions instead")]
196    pub fn with_version(mut self, version: bool) -> Self {
197        self.versions = version;
198        self
199    }
200
201    /// Change the version of this list operation
202    pub fn with_versions(mut self, versions: bool) -> Self {
203        self.versions = versions;
204        self
205    }
206
207    /// Get the version of this list operation
208    #[deprecated(since = "0.51.1", note = "use versions instead")]
209    pub fn version(&self) -> bool {
210        self.versions
211    }
212
213    /// Get the version of this list operation
214    pub fn versions(&self) -> bool {
215        self.versions
216    }
217
218    /// Change the deleted of this list operation
219    pub fn with_deleted(mut self, deleted: bool) -> Self {
220        self.deleted = deleted;
221        self
222    }
223
224    /// Get the deleted of this list operation
225    pub fn deleted(&self) -> bool {
226        self.deleted
227    }
228}
229
230/// Args for `presign` operation.
231///
232/// The path must be normalized.
233#[derive(Debug, Clone)]
234pub struct OpPresign {
235    expire: Duration,
236
237    op: PresignOperation,
238}
239
240impl OpPresign {
241    /// Create a new `OpPresign`.
242    pub fn new(op: impl Into<PresignOperation>, expire: Duration) -> Self {
243        Self {
244            op: op.into(),
245            expire,
246        }
247    }
248
249    /// Get operation from op.
250    pub fn operation(&self) -> &PresignOperation {
251        &self.op
252    }
253
254    /// Get expire from op.
255    pub fn expire(&self) -> Duration {
256        self.expire
257    }
258
259    /// Consume OpPresign into (Duration, PresignOperation)
260    pub fn into_parts(self) -> (Duration, PresignOperation) {
261        (self.expire, self.op)
262    }
263}
264
265/// Presign operation used for presign.
266#[derive(Debug, Clone)]
267#[non_exhaustive]
268pub enum PresignOperation {
269    /// Presign a stat(head) operation.
270    Stat(OpStat),
271    /// Presign a read operation.
272    Read(OpRead),
273    /// Presign a write operation.
274    Write(OpWrite),
275    /// Presign a delete operation.
276    Delete(OpDelete),
277}
278
279impl From<OpStat> for PresignOperation {
280    fn from(op: OpStat) -> Self {
281        Self::Stat(op)
282    }
283}
284
285impl From<OpRead> for PresignOperation {
286    fn from(v: OpRead) -> Self {
287        Self::Read(v)
288    }
289}
290
291impl From<OpWrite> for PresignOperation {
292    fn from(v: OpWrite) -> Self {
293        Self::Write(v)
294    }
295}
296
297impl From<OpDelete> for PresignOperation {
298    fn from(v: OpDelete) -> Self {
299        Self::Delete(v)
300    }
301}
302
303/// Args for `read` operation.
304#[derive(Debug, Clone, Default)]
305pub struct OpRead {
306    range: BytesRange,
307    if_match: Option<String>,
308    if_none_match: Option<String>,
309    if_modified_since: Option<DateTime<Utc>>,
310    if_unmodified_since: Option<DateTime<Utc>>,
311    override_content_type: Option<String>,
312    override_cache_control: Option<String>,
313    override_content_disposition: Option<String>,
314    version: Option<String>,
315}
316
317impl OpRead {
318    /// Create a default `OpRead` which will read whole content of path.
319    pub fn new() -> Self {
320        Self::default()
321    }
322
323    /// Set the range of the option
324    pub fn with_range(mut self, range: BytesRange) -> Self {
325        self.range = range;
326        self
327    }
328
329    /// Get range from option
330    pub fn range(&self) -> BytesRange {
331        self.range
332    }
333
334    /// Returns a mutable range to allow updating.
335    pub(crate) fn range_mut(&mut self) -> &mut BytesRange {
336        &mut self.range
337    }
338
339    /// Sets the content-disposition header that should be sent back by the remote read operation.
340    pub fn with_override_content_disposition(mut self, content_disposition: &str) -> Self {
341        self.override_content_disposition = Some(content_disposition.into());
342        self
343    }
344
345    /// Returns the content-disposition header that should be sent back by the remote read
346    /// operation.
347    pub fn override_content_disposition(&self) -> Option<&str> {
348        self.override_content_disposition.as_deref()
349    }
350
351    /// Sets the cache-control header that should be sent back by the remote read operation.
352    pub fn with_override_cache_control(mut self, cache_control: &str) -> Self {
353        self.override_cache_control = Some(cache_control.into());
354        self
355    }
356
357    /// Returns the cache-control header that should be sent back by the remote read operation.
358    pub fn override_cache_control(&self) -> Option<&str> {
359        self.override_cache_control.as_deref()
360    }
361
362    /// Sets the content-type header that should be sent back by the remote read operation.
363    pub fn with_override_content_type(mut self, content_type: &str) -> Self {
364        self.override_content_type = Some(content_type.into());
365        self
366    }
367
368    /// Returns the content-type header that should be sent back by the remote read operation.
369    pub fn override_content_type(&self) -> Option<&str> {
370        self.override_content_type.as_deref()
371    }
372
373    /// Set the If-Match of the option
374    pub fn with_if_match(mut self, if_match: &str) -> Self {
375        self.if_match = Some(if_match.to_string());
376        self
377    }
378
379    /// Get If-Match from option
380    pub fn if_match(&self) -> Option<&str> {
381        self.if_match.as_deref()
382    }
383
384    /// Set the If-None-Match of the option
385    pub fn with_if_none_match(mut self, if_none_match: &str) -> Self {
386        self.if_none_match = Some(if_none_match.to_string());
387        self
388    }
389
390    /// Get If-None-Match from option
391    pub fn if_none_match(&self) -> Option<&str> {
392        self.if_none_match.as_deref()
393    }
394
395    /// Set the If-Modified-Since of the option
396    pub fn with_if_modified_since(mut self, v: DateTime<Utc>) -> Self {
397        self.if_modified_since = Some(v);
398        self
399    }
400
401    /// Get If-Modified-Since from option
402    pub fn if_modified_since(&self) -> Option<DateTime<Utc>> {
403        self.if_modified_since
404    }
405
406    /// Set the If-Unmodified-Since of the option
407    pub fn with_if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
408        self.if_unmodified_since = Some(v);
409        self
410    }
411
412    /// Get If-Unmodified-Since from option
413    pub fn if_unmodified_since(&self) -> Option<DateTime<Utc>> {
414        self.if_unmodified_since
415    }
416
417    /// Set the version of the option
418    pub fn with_version(mut self, version: &str) -> Self {
419        self.version = Some(version.to_string());
420        self
421    }
422
423    /// Get version from option
424    pub fn version(&self) -> Option<&str> {
425        self.version.as_deref()
426    }
427}
428
429/// Args for reader operation.
430#[derive(Debug, Clone)]
431pub struct OpReader {
432    /// The concurrent requests that reader can send.
433    concurrent: usize,
434    /// The chunk size of each request.
435    chunk: Option<usize>,
436    /// The gap size of each request.
437    gap: Option<usize>,
438}
439
440impl Default for OpReader {
441    fn default() -> Self {
442        Self {
443            concurrent: 1,
444            chunk: None,
445            gap: None,
446        }
447    }
448}
449
450impl OpReader {
451    /// Create a new `OpReader`.
452    pub fn new() -> Self {
453        Self::default()
454    }
455
456    /// Set the concurrent of the option
457    pub fn with_concurrent(mut self, concurrent: usize) -> Self {
458        self.concurrent = concurrent.max(1);
459        self
460    }
461
462    /// Get concurrent from option
463    pub fn concurrent(&self) -> usize {
464        self.concurrent
465    }
466
467    /// Set the chunk of the option
468    pub fn with_chunk(mut self, chunk: usize) -> Self {
469        self.chunk = Some(chunk.max(1));
470        self
471    }
472
473    /// Get chunk from option
474    pub fn chunk(&self) -> Option<usize> {
475        self.chunk
476    }
477
478    /// Set the gap of the option
479    pub fn with_gap(mut self, gap: usize) -> Self {
480        self.gap = Some(gap.max(1));
481        self
482    }
483
484    /// Get gap from option
485    pub fn gap(&self) -> Option<usize> {
486        self.gap
487    }
488}
489
490/// Args for `stat` operation.
491#[derive(Debug, Clone, Default)]
492pub struct OpStat {
493    if_match: Option<String>,
494    if_none_match: Option<String>,
495    if_modified_since: Option<DateTime<Utc>>,
496    if_unmodified_since: Option<DateTime<Utc>>,
497    override_content_type: Option<String>,
498    override_cache_control: Option<String>,
499    override_content_disposition: Option<String>,
500    version: Option<String>,
501}
502
503impl OpStat {
504    /// Create a new `OpStat`.
505    pub fn new() -> Self {
506        Self::default()
507    }
508
509    /// Set the If-Match of the option
510    pub fn with_if_match(mut self, if_match: &str) -> Self {
511        self.if_match = Some(if_match.to_string());
512        self
513    }
514
515    /// Get If-Match from option
516    pub fn if_match(&self) -> Option<&str> {
517        self.if_match.as_deref()
518    }
519
520    /// Set the If-None-Match of the option
521    pub fn with_if_none_match(mut self, if_none_match: &str) -> Self {
522        self.if_none_match = Some(if_none_match.to_string());
523        self
524    }
525
526    /// Get If-None-Match from option
527    pub fn if_none_match(&self) -> Option<&str> {
528        self.if_none_match.as_deref()
529    }
530
531    /// Set the If-Modified-Since of the option
532    pub fn with_if_modified_since(mut self, v: DateTime<Utc>) -> Self {
533        self.if_modified_since = Some(v);
534        self
535    }
536
537    /// Get If-Modified-Since from option
538    pub fn if_modified_since(&self) -> Option<DateTime<Utc>> {
539        self.if_modified_since
540    }
541
542    /// Set the If-Unmodified-Since of the option
543    pub fn with_if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
544        self.if_unmodified_since = Some(v);
545        self
546    }
547
548    /// Get If-Unmodified-Since from option
549    pub fn if_unmodified_since(&self) -> Option<DateTime<Utc>> {
550        self.if_unmodified_since
551    }
552
553    /// Sets the content-disposition header that should be sent back by the remote read operation.
554    pub fn with_override_content_disposition(mut self, content_disposition: &str) -> Self {
555        self.override_content_disposition = Some(content_disposition.into());
556        self
557    }
558
559    /// Returns the content-disposition header that should be sent back by the remote read
560    /// operation.
561    pub fn override_content_disposition(&self) -> Option<&str> {
562        self.override_content_disposition.as_deref()
563    }
564
565    /// Sets the cache-control header that should be sent back by the remote read operation.
566    pub fn with_override_cache_control(mut self, cache_control: &str) -> Self {
567        self.override_cache_control = Some(cache_control.into());
568        self
569    }
570
571    /// Returns the cache-control header that should be sent back by the remote read operation.
572    pub fn override_cache_control(&self) -> Option<&str> {
573        self.override_cache_control.as_deref()
574    }
575
576    /// Sets the content-type header that should be sent back by the remote read operation.
577    pub fn with_override_content_type(mut self, content_type: &str) -> Self {
578        self.override_content_type = Some(content_type.into());
579        self
580    }
581
582    /// Returns the content-type header that should be sent back by the remote read operation.
583    pub fn override_content_type(&self) -> Option<&str> {
584        self.override_content_type.as_deref()
585    }
586
587    /// Set the version of the option
588    pub fn with_version(mut self, version: &str) -> Self {
589        self.version = Some(version.to_string());
590        self
591    }
592
593    /// Get version from option
594    pub fn version(&self) -> Option<&str> {
595        self.version.as_deref()
596    }
597}
598
599/// Args for `write` operation.
600#[derive(Debug, Clone, Default)]
601pub struct OpWrite {
602    append: bool,
603    concurrent: usize,
604    content_type: Option<String>,
605    content_disposition: Option<String>,
606    content_encoding: Option<String>,
607    cache_control: Option<String>,
608    if_match: Option<String>,
609    if_none_match: Option<String>,
610    if_not_exists: bool,
611    user_metadata: Option<HashMap<String, String>>,
612}
613
614impl OpWrite {
615    /// Create a new `OpWrite`.
616    ///
617    /// If input path is not a file path, an error will be returned.
618    pub fn new() -> Self {
619        Self::default()
620    }
621
622    /// Get the append from op.
623    ///
624    /// The append is the flag to indicate that this write operation is an append operation.
625    pub fn append(&self) -> bool {
626        self.append
627    }
628
629    /// Set the append mode of op.
630    ///
631    /// If the append mode is set, the data will be appended to the end of the file.
632    ///
633    /// # Notes
634    ///
635    /// Service could return `Unsupported` if the underlying storage does not support append.
636    pub fn with_append(mut self, append: bool) -> Self {
637        self.append = append;
638        self
639    }
640
641    /// Get the content type from option
642    pub fn content_type(&self) -> Option<&str> {
643        self.content_type.as_deref()
644    }
645
646    /// Set the content type of option
647    pub fn with_content_type(mut self, content_type: &str) -> Self {
648        self.content_type = Some(content_type.to_string());
649        self
650    }
651
652    /// Get the content disposition from option
653    pub fn content_disposition(&self) -> Option<&str> {
654        self.content_disposition.as_deref()
655    }
656
657    /// Set the content disposition of option
658    pub fn with_content_disposition(mut self, content_disposition: &str) -> Self {
659        self.content_disposition = Some(content_disposition.to_string());
660        self
661    }
662
663    /// Get the content encoding from option
664    pub fn content_encoding(&self) -> Option<&str> {
665        self.content_encoding.as_deref()
666    }
667
668    /// Set the content encoding of option
669    pub fn with_content_encoding(mut self, content_encoding: &str) -> Self {
670        self.content_encoding = Some(content_encoding.to_string());
671        self
672    }
673
674    /// Get the cache control from option
675    pub fn cache_control(&self) -> Option<&str> {
676        self.cache_control.as_deref()
677    }
678
679    /// Set the content type of option
680    pub fn with_cache_control(mut self, cache_control: &str) -> Self {
681        self.cache_control = Some(cache_control.to_string());
682        self
683    }
684
685    /// Get the concurrent.
686    pub fn concurrent(&self) -> usize {
687        self.concurrent
688    }
689
690    /// Set the maximum concurrent write task amount.
691    pub fn with_concurrent(mut self, concurrent: usize) -> Self {
692        self.concurrent = concurrent;
693        self
694    }
695
696    /// Set the If-Match of the option
697    pub fn with_if_match(mut self, s: &str) -> Self {
698        self.if_match = Some(s.to_string());
699        self
700    }
701
702    /// Get If-Match from option
703    pub fn if_match(&self) -> Option<&str> {
704        self.if_match.as_deref()
705    }
706
707    /// Set the If-None-Match of the option
708    pub fn with_if_none_match(mut self, s: &str) -> Self {
709        self.if_none_match = Some(s.to_string());
710        self
711    }
712
713    /// Get If-None-Match from option
714    pub fn if_none_match(&self) -> Option<&str> {
715        self.if_none_match.as_deref()
716    }
717
718    /// Set the If-Not-Exist of the option
719    pub fn with_if_not_exists(mut self, b: bool) -> Self {
720        self.if_not_exists = b;
721        self
722    }
723
724    /// Get If-Not-Exist from option
725    pub fn if_not_exists(&self) -> bool {
726        self.if_not_exists
727    }
728
729    /// Set the user defined metadata of the op
730    pub fn with_user_metadata(mut self, metadata: HashMap<String, String>) -> Self {
731        self.user_metadata = Some(metadata);
732        self
733    }
734
735    /// Get the user defined metadata from the op
736    pub fn user_metadata(&self) -> Option<&HashMap<String, String>> {
737        self.user_metadata.as_ref()
738    }
739}
740
741/// Args for `writer` operation.
742#[derive(Debug, Clone, Default)]
743pub struct OpWriter {
744    chunk: Option<usize>,
745}
746
747impl OpWriter {
748    /// Create a new `OpWriter`.
749    pub fn new() -> Self {
750        Self::default()
751    }
752
753    /// Get the chunk from op.
754    ///
755    /// The chunk is used by service to decide the chunk size of the underlying writer.
756    pub fn chunk(&self) -> Option<usize> {
757        self.chunk
758    }
759
760    /// Set the chunk of op.
761    ///
762    /// If chunk is set, the data will be chunked by the underlying writer.
763    ///
764    /// ## NOTE
765    ///
766    /// Service could have their own minimum chunk size while perform write
767    /// operations like multipart uploads. So the chunk size may be larger than
768    /// the given buffer size.
769    pub fn with_chunk(mut self, chunk: usize) -> Self {
770        self.chunk = Some(chunk);
771        self
772    }
773}
774
775/// Args for `copy` operation.
776#[derive(Debug, Clone, Default)]
777pub struct OpCopy {}
778
779impl OpCopy {
780    /// Create a new `OpCopy`.
781    pub fn new() -> Self {
782        Self::default()
783    }
784}
785
786/// Args for `rename` operation.
787#[derive(Debug, Clone, Default)]
788pub struct OpRename {}
789
790impl OpRename {
791    /// Create a new `OpMove`.
792    pub fn new() -> Self {
793        Self::default()
794    }
795}