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