#
tokens: 38181/50000 1/1362 files (page 52/55)
lines: off (toggle) GitHub
raw markdown copy
This is page 52 of 55. Use http://codebase.md/apache/opendal?page={x} to view the full context.

# Directory Structure

```
├── .asf.yaml
├── .config
│   └── nextest.toml
├── .devcontainer
│   ├── devcontainer.json
│   └── post_create.sh
├── .editorconfig
├── .env.example
├── .gitattributes
├── .github
│   ├── actions
│   │   ├── fuzz_test
│   │   │   └── action.yaml
│   │   ├── setup
│   │   │   └── action.yaml
│   │   ├── setup-hadoop
│   │   │   └── action.yaml
│   │   ├── setup-ocaml
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_c
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_cpp
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_go
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_java
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_nodejs
│   │   │   └── action.yaml
│   │   ├── test_behavior_binding_python
│   │   │   └── action.yaml
│   │   ├── test_behavior_core
│   │   │   └── action.yaml
│   │   └── test_behavior_integration_object_store
│   │       └── action.yml
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── 1-bug-report.yml
│   │   ├── 2-feature-request.yml
│   │   ├── 3-new-release.md
│   │   └── config.yml
│   ├── pull_request_template.md
│   ├── release.yml
│   ├── scripts
│   │   ├── test_behavior
│   │   │   ├── __init__.py
│   │   │   ├── plan.py
│   │   │   └── test_plan.py
│   │   ├── test_go_binding
│   │   │   ├── generate_test_scheme.py
│   │   │   └── matrix.yaml
│   │   └── weekly_update
│   │       ├── .gitignore
│   │       ├── .python-version
│   │       ├── main.py
│   │       ├── pyproject.toml
│   │       ├── README.md
│   │       └── uv.lock
│   ├── services
│   │   ├── aliyun_drive
│   │   │   └── aliyun_drive
│   │   │       └── disable_action.yml
│   │   ├── alluxio
│   │   │   └── alluxio
│   │   │       └── action.yml
│   │   ├── azblob
│   │   │   ├── azure_azblob
│   │   │   │   └── action.yml
│   │   │   └── azurite_azblob
│   │   │       └── action.yml
│   │   ├── azdls
│   │   │   └── azdls
│   │   │       └── action.yml
│   │   ├── azfile
│   │   │   └── azfile
│   │   │       └── action.yml
│   │   ├── b2
│   │   │   └── b2
│   │   │       └── action.yml
│   │   ├── cacache
│   │   │   └── cacache
│   │   │       └── action.yml
│   │   ├── compfs
│   │   │   └── compfs
│   │   │       └── action.yml
│   │   ├── cos
│   │   │   └── cos
│   │   │       └── action.yml
│   │   ├── dashmap
│   │   │   └── dashmap
│   │   │       └── action.yml
│   │   ├── dropbox
│   │   │   └── dropbox
│   │   │       └── disable_action.yml
│   │   ├── etcd
│   │   │   ├── etcd
│   │   │   │   └── action.yml
│   │   │   ├── etcd-cluster
│   │   │   │   └── action.yml
│   │   │   └── etcd-tls
│   │   │       └── action.yml
│   │   ├── fs
│   │   │   └── local_fs
│   │   │       └── action.yml
│   │   ├── ftp
│   │   │   └── vsftpd
│   │   │       └── disable_action.yml
│   │   ├── gcs
│   │   │   ├── gcs
│   │   │   │   └── action.yml
│   │   │   └── gcs_with_default_storage_class
│   │   │       └── action.yml
│   │   ├── gdrive
│   │   │   └── gdrive
│   │   │       └── action.yml
│   │   ├── gridfs
│   │   │   ├── gridfs
│   │   │   │   └── action.yml
│   │   │   └── gridfs_with_basic_auth
│   │   │       └── action.yml
│   │   ├── hdfs
│   │   │   ├── hdfs_cluster
│   │   │   │   └── action.yml
│   │   │   ├── hdfs_cluster_with_atomic_write_dir
│   │   │   │   └── action.yml
│   │   │   ├── hdfs_default
│   │   │   │   └── action.yml
│   │   │   ├── hdfs_default_gcs
│   │   │   │   └── action.yml
│   │   │   ├── hdfs_default_on_azurite_azblob
│   │   │   │   └── action.yml
│   │   │   ├── hdfs_default_on_minio_s3
│   │   │   │   └── action.yml
│   │   │   └── hdfs_default_with_atomic_write_dir
│   │   │       └── action.yml
│   │   ├── hdfs_native
│   │   │   └── hdfs_native_cluster
│   │   │       └── action.yml
│   │   ├── http
│   │   │   ├── caddy
│   │   │   │   └── action.yml
│   │   │   └── nginx
│   │   │       └── action.yml
│   │   ├── huggingface
│   │   │   └── huggingface
│   │   │       └── action.yml
│   │   ├── koofr
│   │   │   └── koofr
│   │   │       └── disable_action.yml
│   │   ├── memcached
│   │   │   ├── memcached
│   │   │   │   └── action.yml
│   │   │   └── memcached_with_auth
│   │   │       └── action.yml
│   │   ├── memory
│   │   │   └── memory
│   │   │       └── action.yml
│   │   ├── mini_moka
│   │   │   └── mini_moka
│   │   │       └── action.yml
│   │   ├── moka
│   │   │   └── moka
│   │   │       └── action.yml
│   │   ├── mongodb
│   │   │   ├── mongodb_with_basic_auth
│   │   │   │   └── action.yml
│   │   │   └── mongodb_with_no_auth
│   │   │       └── action.yml
│   │   ├── monoiofs
│   │   │   └── monoiofs
│   │   │       └── action.yml
│   │   ├── mysql
│   │   │   └── mysql
│   │   │       └── action.yml
│   │   ├── oss
│   │   │   ├── oss
│   │   │   │   └── action.yml
│   │   │   └── oss_with_versioning
│   │   │       └── action.yml
│   │   ├── persy
│   │   │   └── persy
│   │   │       └── action.yml
│   │   ├── postgresql
│   │   │   └── postgresql
│   │   │       └── action.yml
│   │   ├── redb
│   │   │   └── redb
│   │   │       └── action.yml
│   │   ├── redis
│   │   │   ├── dragonfly
│   │   │   │   └── action.yml
│   │   │   ├── kvrocks
│   │   │   │   └── action.yml
│   │   │   ├── redis
│   │   │   │   └── action.yml
│   │   │   ├── redis_tls
│   │   │   │   └── action.yml
│   │   │   ├── redis_with_cluster
│   │   │   │   └── action.yml
│   │   │   └── redis_with_cluster_tls
│   │   │       └── action.yml
│   │   ├── rocksdb
│   │   │   └── rocksdb
│   │   │       └── action.yml
│   │   ├── s3
│   │   │   ├── 0_minio_s3
│   │   │   │   └── action.yml
│   │   │   ├── aws_s3
│   │   │   │   └── action.yml
│   │   │   ├── aws_s3_with_list_objects_v1
│   │   │   │   └── action.yml
│   │   │   ├── aws_s3_with_sse_c
│   │   │   │   └── action.yml
│   │   │   ├── aws_s3_with_versioning
│   │   │   │   └── action.yml
│   │   │   ├── aws_s3_with_virtual_host
│   │   │   │   └── action.yml
│   │   │   ├── ceph_radios_s3_with_versioning
│   │   │   │   └── disable_action.yml
│   │   │   ├── ceph_rados_s3
│   │   │   │   └── disable_action.yml
│   │   │   ├── minio_s3_with_anonymous
│   │   │   │   └── action.yml
│   │   │   ├── minio_s3_with_list_objects_v1
│   │   │   │   └── action.yml
│   │   │   ├── minio_s3_with_versioning
│   │   │   │   └── action.yml
│   │   │   └── r2
│   │   │       └── disabled_action.yml
│   │   ├── seafile
│   │   │   └── seafile
│   │   │       └── action.yml
│   │   ├── sftp
│   │   │   ├── sftp
│   │   │   │   └── action.yml
│   │   │   └── sftp_with_default_root
│   │   │       └── action.yml
│   │   ├── sled
│   │   │   ├── sled
│   │   │   │   └── action.yml
│   │   │   └── sled_with_tree
│   │   │       └── action.yml
│   │   ├── sqlite
│   │   │   └── sqlite
│   │   │       └── action.yml
│   │   ├── swift
│   │   │   ├── ceph_rados_swift
│   │   │   │   └── action.yml
│   │   │   └── swift
│   │   │       └── action.yml
│   │   ├── tikv
│   │   │   └── tikv
│   │   │       └── disable_action.yml
│   │   ├── webdav
│   │   │   ├── 0_nginx
│   │   │   │   └── action.yml
│   │   │   ├── jfrog
│   │   │   │   └── disabled_action.yml
│   │   │   ├── nextcloud
│   │   │   │   └── action.yml
│   │   │   ├── nginx_with_empty_password
│   │   │   │   └── action.yml
│   │   │   ├── nginx_with_password
│   │   │   │   └── action.yml
│   │   │   ├── nginx_with_redirect
│   │   │   │   └── action.yml
│   │   │   └── owncloud
│   │   │       └── action.yml
│   │   └── webhdfs
│   │       ├── webhdfs
│   │       │   └── action.yml
│   │       ├── webhdfs_with_list_batch_disabled
│   │       │   └── action.yml
│   │       └── webhdfs_with_user_name
│   │           └── action.yml
│   └── workflows
│       ├── ci_bindings_c.yml
│       ├── ci_bindings_cpp.yml
│       ├── ci_bindings_d.yml
│       ├── ci_bindings_dart.yml
│       ├── ci_bindings_dotnet.yml
│       ├── ci_bindings_go.yml
│       ├── ci_bindings_haskell.yml
│       ├── ci_bindings_java.yml
│       ├── ci_bindings_lua.yml
│       ├── ci_bindings_nodejs.yml
│       ├── ci_bindings_ocaml.yml
│       ├── ci_bindings_php.yml
│       ├── ci_bindings_python.yml
│       ├── ci_bindings_ruby.yml
│       ├── ci_bindings_swift.yml
│       ├── ci_bindings_zig.yml
│       ├── ci_check.yml
│       ├── ci_core.yml
│       ├── ci_integration_dav_server.yml
│       ├── ci_integration_object_store.yml
│       ├── ci_integration_parquet.yml
│       ├── ci_integration_spring.yml
│       ├── ci_integration_unftp_sbe.yml
│       ├── ci_odev.yml
│       ├── ci_weekly_update.yml
│       ├── discussion-thread-link.yml
│       ├── docs.yml
│       ├── full-ci-promote.yml
│       ├── release_dart.yml
│       ├── release_java.yml
│       ├── release_nodejs.yml
│       ├── release_python.yml
│       ├── release_ruby.yml
│       ├── release_rust.yml
│       ├── service_test_ghac.yml
│       ├── test_behavior_binding_c.yml
│       ├── test_behavior_binding_cpp.yml
│       ├── test_behavior_binding_go.yml
│       ├── test_behavior_binding_java.yml
│       ├── test_behavior_binding_nodejs.yml
│       ├── test_behavior_binding_python.yml
│       ├── test_behavior_core.yml
│       ├── test_behavior_integration_object_store.yml
│       ├── test_behavior.yml
│       ├── test_edge.yml
│       └── test_fuzz.yml
├── .gitignore
├── .taplo.toml
├── .typos.toml
├── .vscode
│   └── settings.json
├── .yamlfmt
├── AGENTS.md
├── bindings
│   ├── java
│   │   ├── .cargo
│   │   │   └── config.toml
│   │   ├── .gitignore
│   │   ├── .mvn
│   │   │   └── wrapper
│   │   │       └── maven-wrapper.properties
│   │   ├── Cargo.toml
│   │   ├── DEPENDENCIES.md
│   │   ├── DEPENDENCIES.rust.tsv
│   │   ├── mvnw
│   │   ├── mvnw.cmd
│   │   ├── pom.xml
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── async_operator.rs
│   │   │   ├── convert.rs
│   │   │   ├── error.rs
│   │   │   ├── executor.rs
│   │   │   ├── layer.rs
│   │   │   ├── lib.rs
│   │   │   ├── main
│   │   │   │   ├── java
│   │   │   │   │   └── org
│   │   │   │   │       └── apache
│   │   │   │   │           └── opendal
│   │   │   │   │               ├── AsyncExecutor.java
│   │   │   │   │               ├── AsyncOperator.java
│   │   │   │   │               ├── Capability.java
│   │   │   │   │               ├── Entry.java
│   │   │   │   │               ├── Environment.java
│   │   │   │   │               ├── layer
│   │   │   │   │               │   ├── ConcurrentLimitLayer.java
│   │   │   │   │               │   ├── package-info.java
│   │   │   │   │               │   └── RetryLayer.java
│   │   │   │   │               ├── Layer.java
│   │   │   │   │               ├── ListOptions.java
│   │   │   │   │               ├── Metadata.java
│   │   │   │   │               ├── NativeLibrary.java
│   │   │   │   │               ├── NativeObject.java
│   │   │   │   │               ├── OpenDAL.java
│   │   │   │   │               ├── OpenDALException.java
│   │   │   │   │               ├── Operator.java
│   │   │   │   │               ├── OperatorInfo.java
│   │   │   │   │               ├── OperatorInputStream.java
│   │   │   │   │               ├── OperatorOutputStream.java
│   │   │   │   │               ├── package-info.java
│   │   │   │   │               ├── PresignedRequest.java
│   │   │   │   │               ├── ReadOptions.java
│   │   │   │   │               ├── ServiceConfig.java
│   │   │   │   │               ├── StatOptions.java
│   │   │   │   │               └── WriteOptions.java
│   │   │   │   └── resources
│   │   │   │       ├── bindings.properties
│   │   │   │       └── META-INF
│   │   │   │           └── NOTICE
│   │   │   ├── operator_input_stream.rs
│   │   │   ├── operator_output_stream.rs
│   │   │   ├── operator.rs
│   │   │   ├── test
│   │   │   │   └── java
│   │   │   │       └── org
│   │   │   │           └── apache
│   │   │   │               └── opendal
│   │   │   │                   └── test
│   │   │   │                       ├── AsyncExecutorTest.java
│   │   │   │                       ├── behavior
│   │   │   │                       │   ├── AsyncCopyTest.java
│   │   │   │                       │   ├── AsyncCreateDirTest.java
│   │   │   │                       │   ├── AsyncListTest.java
│   │   │   │                       │   ├── AsyncPresignTest.java
│   │   │   │                       │   ├── AsyncReadOnlyTest.java
│   │   │   │                       │   ├── AsyncRenameTest.java
│   │   │   │                       │   ├── AsyncStatOptionsTest.java
│   │   │   │                       │   ├── AsyncWriteOptionsTest.java
│   │   │   │                       │   ├── AsyncWriteTest.java
│   │   │   │                       │   ├── BehaviorExtension.java
│   │   │   │                       │   ├── BehaviorTestBase.java
│   │   │   │                       │   ├── BlockingCopyTest.java
│   │   │   │                       │   ├── BlockingCreateDirTest.java
│   │   │   │                       │   ├── BlockingListTest.java
│   │   │   │                       │   ├── BlockingReadOnlyTest.java
│   │   │   │                       │   ├── BlockingRenameTest.java
│   │   │   │                       │   ├── BlockingStatOptionsTest.java
│   │   │   │                       │   ├── BlockingWriteOptionTest.java
│   │   │   │                       │   ├── BlockingWriteTest.java
│   │   │   │                       │   └── RegressionTest.java
│   │   │   │                       ├── condition
│   │   │   │                       │   └── OpenDALExceptionCondition.java
│   │   │   │                       ├── LayerTest.java
│   │   │   │                       ├── MetadataTest.java
│   │   │   │                       ├── OperatorDuplicateTest.java
│   │   │   │                       ├── OperatorInfoTest.java
│   │   │   │                       ├── OperatorInputOutputStreamTest.java
│   │   │   │                       ├── OperatorUtf8DecodeTest.java
│   │   │   │                       └── UtilityTest.java
│   │   │   └── utility.rs
│   │   ├── tools
│   │   │   └── build.py
│   │   ├── upgrade.md
│   │   └── users.md
│   ├── nodejs
│   │   ├── .cargo
│   │   │   └── config.toml
│   │   ├── .gitignore
│   │   ├── .node-version
│   │   ├── .npmignore
│   │   ├── .npmrc
│   │   ├── .prettierignore
│   │   ├── benchmark
│   │   │   ├── deno.ts
│   │   │   ├── node.js
│   │   │   └── README.md
│   │   ├── build.rs
│   │   ├── Cargo.toml
│   │   ├── CONTRIBUTING.md
│   │   ├── DEPENDENCIES.md
│   │   ├── DEPENDENCIES.rust.tsv
│   │   ├── devbox.json
│   │   ├── devbox.lock
│   │   ├── generated.d.ts
│   │   ├── generated.js
│   │   ├── index.cjs
│   │   ├── index.d.ts
│   │   ├── index.mjs
│   │   ├── npm
│   │   │   ├── darwin-arm64
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── darwin-x64
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── linux-arm64-gnu
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── linux-arm64-musl
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── linux-x64-gnu
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── linux-x64-musl
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   ├── win32-arm64-msvc
│   │   │   │   ├── package.json
│   │   │   │   └── README.md
│   │   │   └── win32-x64-msvc
│   │   │       ├── package.json
│   │   │       └── README.md
│   │   ├── package.json
│   │   ├── pnpm-lock.yaml
│   │   ├── README.md
│   │   ├── scripts
│   │   │   └── header.mjs
│   │   ├── src
│   │   │   ├── capability.rs
│   │   │   ├── layer.rs
│   │   │   ├── lib.rs
│   │   │   └── options.rs
│   │   ├── tests
│   │   │   ├── service.test.mjs
│   │   │   ├── suites
│   │   │   │   ├── async.suite.mjs
│   │   │   │   ├── asyncDeleteOptions.suite.mjs
│   │   │   │   ├── asyncLister.suite.mjs
│   │   │   │   ├── asyncListOptions.suite.mjs
│   │   │   │   ├── asyncReadOptions.suite.mjs
│   │   │   │   ├── asyncStatOptions.suite.mjs
│   │   │   │   ├── asyncWriteOptions.suite.mjs
│   │   │   │   ├── index.mjs
│   │   │   │   ├── layer.suite.mjs
│   │   │   │   ├── services.suite.mjs
│   │   │   │   ├── sync.suite.mjs
│   │   │   │   ├── syncDeleteOptions.suite.mjs
│   │   │   │   ├── syncLister.suite.mjs
│   │   │   │   ├── syncListOptions.suite.mjs
│   │   │   │   ├── syncReadOptions.suite.mjs
│   │   │   │   ├── syncStatOptions.suite.mjs
│   │   │   │   └── syncWriteOptions.suite.mjs
│   │   │   └── utils.mjs
│   │   ├── theme
│   │   │   ├── index.tsx
│   │   │   └── package.json
│   │   ├── tsconfig.json
│   │   ├── tsconfig.theme.json
│   │   ├── typedoc.json
│   │   ├── upgrade.md
│   │   └── vitest.config.mjs
│   ├── python
│   │   ├── .gitignore
│   │   ├── benchmark
│   │   │   ├── async_opendal_benchmark.py
│   │   │   ├── async_origin_s3_benchmark_with_gevent.py
│   │   │   └── README.md
│   │   ├── Cargo.toml
│   │   ├── CONTRIBUTING.md
│   │   ├── DEPENDENCIES.md
│   │   ├── DEPENDENCIES.rust.tsv
│   │   ├── docs
│   │   │   ├── api
│   │   │   │   ├── async_file.md
│   │   │   │   ├── async_operator.md
│   │   │   │   ├── capability.md
│   │   │   │   ├── exceptions.md
│   │   │   │   ├── file.md
│   │   │   │   ├── layers.md
│   │   │   │   ├── operator.md
│   │   │   │   └── types.md
│   │   │   └── index.md
│   │   ├── justfile
│   │   ├── mkdocs.yml
│   │   ├── pyproject.toml
│   │   ├── pyrightconfig.json
│   │   ├── python
│   │   │   └── opendal
│   │   │       ├── __init__.py
│   │   │       ├── capability.pyi
│   │   │       ├── exceptions.pyi
│   │   │       ├── file.pyi
│   │   │       ├── layers.pyi
│   │   │       ├── operator.pyi
│   │   │       ├── py.typed
│   │   │       ├── services.pyi
│   │   │       └── types.pyi
│   │   ├── README.md
│   │   ├── ruff.toml
│   │   ├── src
│   │   │   ├── capability.rs
│   │   │   ├── errors.rs
│   │   │   ├── file.rs
│   │   │   ├── layers.rs
│   │   │   ├── lib.rs
│   │   │   ├── lister.rs
│   │   │   ├── metadata.rs
│   │   │   ├── operator.rs
│   │   │   ├── options.rs
│   │   │   ├── services.rs
│   │   │   └── utils.rs
│   │   ├── template
│   │   │   └── module.html.jinja2
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_async_check.py
│   │   │   ├── test_async_copy.py
│   │   │   ├── test_async_delete.py
│   │   │   ├── test_async_exists.py
│   │   │   ├── test_async_list.py
│   │   │   ├── test_async_pickle_types.py
│   │   │   ├── test_async_rename.py
│   │   │   ├── test_capability.py
│   │   │   ├── test_exceptions.py
│   │   │   ├── test_pickle_rw.py
│   │   │   ├── test_read.py
│   │   │   ├── test_sync_check.py
│   │   │   ├── test_sync_copy.py
│   │   │   ├── test_sync_delete.py
│   │   │   ├── test_sync_exists.py
│   │   │   ├── test_sync_list.py
│   │   │   ├── test_sync_pickle_types.py
│   │   │   ├── test_sync_rename.py
│   │   │   └── test_write.py
│   │   ├── upgrade.md
│   │   ├── users.md
│   │   └── uv.lock
│   └── README.md
├── CHANGELOG.md
├── CITATION.cff
├── CLAUDE.md
├── CONTRIBUTING.md
├── core
│   ├── benches
│   │   ├── ops
│   │   │   ├── main.rs
│   │   │   ├── read.rs
│   │   │   ├── README.md
│   │   │   ├── utils.rs
│   │   │   └── write.rs
│   │   ├── README.md
│   │   ├── types
│   │   │   ├── buffer.rs
│   │   │   ├── main.rs
│   │   │   ├── README.md
│   │   │   └── tasks.rs
│   │   ├── vs_fs
│   │   │   ├── Cargo.toml
│   │   │   ├── README.md
│   │   │   └── src
│   │   │       └── main.rs
│   │   └── vs_s3
│   │       ├── Cargo.toml
│   │       ├── README.md
│   │       └── src
│   │           └── main.rs
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── CHANGELOG.md
│   ├── CONTRIBUTING.md
│   ├── core
│   │   ├── Cargo.toml
│   │   └── src
│   │       ├── blocking
│   │       │   ├── delete.rs
│   │       │   ├── list.rs
│   │       │   ├── mod.rs
│   │       │   ├── operator.rs
│   │       │   ├── read
│   │       │   │   ├── buffer_iterator.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── reader.rs
│   │       │   │   ├── std_bytes_iterator.rs
│   │       │   │   └── std_reader.rs
│   │       │   └── write
│   │       │       ├── mod.rs
│   │       │       ├── std_writer.rs
│   │       │       └── writer.rs
│   │       ├── docs
│   │       │   ├── comparisons
│   │       │   │   ├── mod.rs
│   │       │   │   └── vs_object_store.md
│   │       │   ├── concepts.rs
│   │       │   ├── internals
│   │       │   │   ├── accessor.rs
│   │       │   │   ├── layer.rs
│   │       │   │   └── mod.rs
│   │       │   ├── mod.rs
│   │       │   ├── performance
│   │       │   │   ├── concurrent_write.md
│   │       │   │   ├── http_optimization.md
│   │       │   │   └── mod.rs
│   │       │   ├── rfcs
│   │       │   │   ├── 0000_example.md
│   │       │   │   ├── 0041_object_native_api.md
│   │       │   │   ├── 0044_error_handle.md
│   │       │   │   ├── 0057_auto_region.md
│   │       │   │   ├── 0069_object_stream.md
│   │       │   │   ├── 0090_limited_reader.md
│   │       │   │   ├── 0112_path_normalization.md
│   │       │   │   ├── 0191_async_streaming_io.md
│   │       │   │   ├── 0203_remove_credential.md
│   │       │   │   ├── 0221_create_dir.md
│   │       │   │   ├── 0247_retryable_error.md
│   │       │   │   ├── 0293_object_id.md
│   │       │   │   ├── 0337_dir_entry.md
│   │       │   │   ├── 0409_accessor_capabilities.md
│   │       │   │   ├── 0413_presign.md
│   │       │   │   ├── 0423_command_line_interface.md
│   │       │   │   ├── 0429_init_from_iter.md
│   │       │   │   ├── 0438_multipart.md
│   │       │   │   ├── 0443_gateway.md
│   │       │   │   ├── 0501_new_builder.md
│   │       │   │   ├── 0554_write_refactor.md
│   │       │   │   ├── 0561_list_metadata_reuse.md
│   │       │   │   ├── 0599_blocking_api.md
│   │       │   │   ├── 0623_redis_service.md
│   │       │   │   ├── 0627_split_capabilities.md
│   │       │   │   ├── 0661_path_in_accessor.md
│   │       │   │   ├── 0793_generic_kv_services.md
│   │       │   │   ├── 0926_object_reader.md
│   │       │   │   ├── 0977_refactor_error.md
│   │       │   │   ├── 1085_object_handler.md
│   │       │   │   ├── 1391_object_metadataer.md
│   │       │   │   ├── 1398_query_based_metadata.md
│   │       │   │   ├── 1420_object_writer.md
│   │       │   │   ├── 1477_remove_object_concept.md
│   │       │   │   ├── 1735_operation_extension.md
│   │       │   │   ├── 2083_writer_sink_api.md
│   │       │   │   ├── 2133_append_api.md
│   │       │   │   ├── 2299_chain_based_operator_api.md
│   │       │   │   ├── 2602_object_versioning.md
│   │       │   │   ├── 2758_merge_append_into_write.md
│   │       │   │   ├── 2774_lister_api.md
│   │       │   │   ├── 2779_list_with_metakey.md
│   │       │   │   ├── 2852_native_capability.md
│   │       │   │   ├── 2884_merge_range_read_into_read.md
│   │       │   │   ├── 3017_remove_write_copy_from.md
│   │       │   │   ├── 3197_config.md
│   │       │   │   ├── 3232_align_list_api.md
│   │       │   │   ├── 3243_list_prefix.md
│   │       │   │   ├── 3356_lazy_reader.md
│   │       │   │   ├── 3526_list_recursive.md
│   │       │   │   ├── 3574_concurrent_stat_in_list.md
│   │       │   │   ├── 3734_buffered_reader.md
│   │       │   │   ├── 3898_concurrent_writer.md
│   │       │   │   ├── 3911_deleter_api.md
│   │       │   │   ├── 4382_range_based_read.md
│   │       │   │   ├── 4638_executor.md
│   │       │   │   ├── 5314_remove_metakey.md
│   │       │   │   ├── 5444_operator_from_uri.md
│   │       │   │   ├── 5479_context.md
│   │       │   │   ├── 5485_conditional_reader.md
│   │       │   │   ├── 5495_list_with_deleted.md
│   │       │   │   ├── 5556_write_returns_metadata.md
│   │       │   │   ├── 5871_read_returns_metadata.md
│   │       │   │   ├── 6189_remove_native_blocking.md
│   │       │   │   ├── 6209_glob_support.md
│   │       │   │   ├── 6213_options_api.md
│   │       │   │   ├── 6370_foyer_integration.md
│   │       │   │   ├── 6678_simulate_layer.md
│   │       │   │   ├── 6707_capability_override_layer.md
│   │       │   │   ├── 6817_checksum.md
│   │       │   │   ├── 6828_core.md
│   │       │   │   ├── 7130_route_layer.md
│   │       │   │   ├── mod.rs
│   │       │   │   └── README.md
│   │       │   └── upgrade.md
│   │       ├── layers
│   │       │   ├── complete.rs
│   │       │   ├── correctness_check.rs
│   │       │   ├── error_context.rs
│   │       │   ├── http_client.rs
│   │       │   ├── mod.rs
│   │       │   ├── simulate.rs
│   │       │   └── type_eraser.rs
│   │       ├── lib.rs
│   │       ├── raw
│   │       │   ├── accessor.rs
│   │       │   ├── atomic_util.rs
│   │       │   ├── enum_utils.rs
│   │       │   ├── futures_util.rs
│   │       │   ├── http_util
│   │       │   │   ├── body.rs
│   │       │   │   ├── bytes_content_range.rs
│   │       │   │   ├── bytes_range.rs
│   │       │   │   ├── client.rs
│   │       │   │   ├── error.rs
│   │       │   │   ├── header.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── multipart.rs
│   │       │   │   └── uri.rs
│   │       │   ├── layer.rs
│   │       │   ├── mod.rs
│   │       │   ├── oio
│   │       │   │   ├── buf
│   │       │   │   │   ├── flex_buf.rs
│   │       │   │   │   ├── mod.rs
│   │       │   │   │   ├── pooled_buf.rs
│   │       │   │   │   └── queue_buf.rs
│   │       │   │   ├── delete
│   │       │   │   │   ├── api.rs
│   │       │   │   │   ├── batch_delete.rs
│   │       │   │   │   ├── mod.rs
│   │       │   │   │   └── one_shot_delete.rs
│   │       │   │   ├── entry.rs
│   │       │   │   ├── list
│   │       │   │   │   ├── api.rs
│   │       │   │   │   ├── flat_list.rs
│   │       │   │   │   ├── hierarchy_list.rs
│   │       │   │   │   ├── mod.rs
│   │       │   │   │   ├── page_list.rs
│   │       │   │   │   └── prefix_list.rs
│   │       │   │   ├── mod.rs
│   │       │   │   ├── read
│   │       │   │   │   ├── api.rs
│   │       │   │   │   └── mod.rs
│   │       │   │   └── write
│   │       │   │       ├── api.rs
│   │       │   │       ├── append_write.rs
│   │       │   │       ├── block_write.rs
│   │       │   │       ├── mod.rs
│   │       │   │       ├── multipart_write.rs
│   │       │   │       ├── one_shot_write.rs
│   │       │   │       └── position_write.rs
│   │       │   ├── operation.rs
│   │       │   ├── ops.rs
│   │       │   ├── path_cache.rs
│   │       │   ├── path.rs
│   │       │   ├── rps.rs
│   │       │   ├── serde_util.rs
│   │       │   ├── std_io_util.rs
│   │       │   ├── time.rs
│   │       │   ├── tokio_util.rs
│   │       │   └── version.rs
│   │       ├── services
│   │       │   ├── memory
│   │       │   │   ├── backend.rs
│   │       │   │   ├── config.rs
│   │       │   │   ├── core.rs
│   │       │   │   ├── deleter.rs
│   │       │   │   ├── docs.md
│   │       │   │   ├── lister.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── writer.rs
│   │       │   └── mod.rs
│   │       └── types
│   │           ├── buffer.rs
│   │           ├── builder.rs
│   │           ├── capability.rs
│   │           ├── context
│   │           │   ├── mod.rs
│   │           │   ├── read.rs
│   │           │   └── write.rs
│   │           ├── delete
│   │           │   ├── deleter.rs
│   │           │   ├── futures_delete_sink.rs
│   │           │   ├── input.rs
│   │           │   └── mod.rs
│   │           ├── entry.rs
│   │           ├── error.rs
│   │           ├── execute
│   │           │   ├── api.rs
│   │           │   ├── executor.rs
│   │           │   ├── executors
│   │           │   │   ├── mod.rs
│   │           │   │   └── tokio_executor.rs
│   │           │   └── mod.rs
│   │           ├── list.rs
│   │           ├── metadata.rs
│   │           ├── mod.rs
│   │           ├── mode.rs
│   │           ├── operator
│   │           │   ├── builder.rs
│   │           │   ├── info.rs
│   │           │   ├── mod.rs
│   │           │   ├── operator_futures.rs
│   │           │   ├── operator.rs
│   │           │   ├── registry.rs
│   │           │   └── uri.rs
│   │           ├── options.rs
│   │           ├── read
│   │           │   ├── buffer_stream.rs
│   │           │   ├── futures_async_reader.rs
│   │           │   ├── futures_bytes_stream.rs
│   │           │   ├── mod.rs
│   │           │   └── reader.rs
│   │           └── write
│   │               ├── buffer_sink.rs
│   │               ├── futures_async_writer.rs
│   │               ├── futures_bytes_sink.rs
│   │               ├── mod.rs
│   │               └── writer.rs
│   ├── DEPENDENCIES.md
│   ├── DEPENDENCIES.rust.tsv
│   ├── edge
│   │   ├── file_write_on_full_disk
│   │   │   ├── Cargo.toml
│   │   │   ├── README.md
│   │   │   └── src
│   │   │       └── main.rs
│   │   ├── README.md
│   │   ├── s3_aws_assume_role_with_web_identity
│   │   │   ├── Cargo.toml
│   │   │   ├── README.md
│   │   │   └── src
│   │   │       └── main.rs
│   │   └── s3_read_on_wasm
│   │       ├── .gitignore
│   │       ├── Cargo.toml
│   │       ├── README.md
│   │       ├── src
│   │       │   └── lib.rs
│   │       └── webdriver.json
│   ├── fuzz
│   │   ├── .gitignore
│   │   ├── Cargo.toml
│   │   ├── fuzz_reader.rs
│   │   ├── fuzz_writer.rs
│   │   └── README.md
│   ├── layers
│   │   ├── async-backtrace
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── await-tree
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── capability-check
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── chaos
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── concurrent-limit
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── dtrace
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── fastmetrics
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── fastrace
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── foyer
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── hotpath
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── immutable-index
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── logging
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── metrics
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── mime-guess
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── observe-metrics-common
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── otelmetrics
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── oteltrace
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── prometheus
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── prometheus-client
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── retry
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── route
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── tail-cut
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── throttle
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── timeout
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   └── tracing
│   │       ├── Cargo.toml
│   │       └── src
│   │           └── lib.rs
│   ├── LICENSE
│   ├── README.md
│   ├── services
│   │   ├── aliyun-drive
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── alluxio
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── azblob
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── azdls
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── azfile
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── azure-common
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       └── lib.rs
│   │   ├── b2
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── cacache
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── cloudflare-kv
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── model.rs
│   │   │       └── writer.rs
│   │   ├── compfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── cos
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── d1
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── model.rs
│   │   │       └── writer.rs
│   │   ├── dashmap
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── dbfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── dropbox
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── builder.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── etcd
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── foundationdb
│   │   │   ├── build.rs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── fs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── ftp
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── err.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── gcs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── uri.rs
│   │   │       └── writer.rs
│   │   ├── gdrive
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── builder.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── ghac
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── github
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── mod.rs
│   │   │       └── writer.rs
│   │   ├── gridfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── hdfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── hdfs-native
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── http
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       └── lib.rs
│   │   ├── huggingface
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       └── lister.rs
│   │   ├── ipfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── ipld.rs
│   │   │       └── lib.rs
│   │   ├── ipmfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── builder.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── koofr
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── lakefs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── memcached
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── binary.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── mini_moka
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── moka
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── mongodb
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── monoiofs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── reader.rs
│   │   │       └── writer.rs
│   │   ├── mysql
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── obs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── onedrive
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── builder.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── graph_model.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── opfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       └── utils.rs
│   │   ├── oss
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── pcloud
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── persy
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── postgresql
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── redb
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── redis
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── delete.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── rocksdb
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── s3
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── compatible_services.md
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── mod.rs
│   │   │       └── writer.rs
│   │   ├── seafile
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── sftp
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── reader.rs
│   │   │       ├── utils.rs
│   │   │       └── writer.rs
│   │   ├── sled
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── sqlite
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── surrealdb
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── swift
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── compatible_services.md
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── tikv
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── upyun
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── vercel-artifacts
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── builder.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       └── writer.rs
│   │   ├── vercel-blob
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── webdav
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       └── writer.rs
│   │   ├── webhdfs
│   │   │   ├── Cargo.toml
│   │   │   └── src
│   │   │       ├── backend.rs
│   │   │       ├── config.rs
│   │   │       ├── core.rs
│   │   │       ├── deleter.rs
│   │   │       ├── docs.md
│   │   │       ├── error.rs
│   │   │       ├── lib.rs
│   │   │       ├── lister.rs
│   │   │       ├── message.rs
│   │   │       └── writer.rs
│   │   └── yandex-disk
│   │       ├── Cargo.toml
│   │       └── src
│   │           ├── backend.rs
│   │           ├── config.rs
│   │           ├── core.rs
│   │           ├── deleter.rs
│   │           ├── docs.md
│   │           ├── error.rs
│   │           ├── lib.rs
│   │           ├── lister.rs
│   │           └── writer.rs
│   ├── src
│   │   └── lib.rs
│   ├── testkit
│   │   ├── Cargo.toml
│   │   └── src
│   │       ├── lib.rs
│   │       ├── read.rs
│   │       ├── utils.rs
│   │       └── write.rs
│   ├── tests
│   │   ├── behavior
│   │   │   ├── async_copy.rs
│   │   │   ├── async_create_dir.rs
│   │   │   ├── async_delete.rs
│   │   │   ├── async_list.rs
│   │   │   ├── async_presign.rs
│   │   │   ├── async_read.rs
│   │   │   ├── async_rename.rs
│   │   │   ├── async_stat.rs
│   │   │   ├── async_write.rs
│   │   │   ├── main.rs
│   │   │   ├── README.md
│   │   │   └── utils.rs
│   │   └── data
│   │       ├── normal_dir
│   │       │   └── .gitkeep
│   │       ├── normal_file.txt
│   │       ├── special_dir  !@#$%^&()_+-=;',
│   │       │   └── .gitkeep
│   │       └── special_file  !@#$%^&()_+-=;',.txt
│   ├── upgrade.md
│   └── users.md
├── deny.toml
├── DEPENDENCIES.md
├── dev
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── README.md
│   └── src
│       ├── generate
│       │   ├── java.j2
│       │   ├── java.rs
│       │   ├── mod.rs
│       │   ├── parser.rs
│       │   ├── python.j2
│       │   └── python.rs
│       ├── main.rs
│       └── release
│           ├── mod.rs
│           └── package.rs
├── doap.rdf
├── fixtures
│   ├── alluxio
│   │   └── docker-compose-alluxio.yml
│   ├── azblob
│   │   └── docker-compose-azurite.yml
│   ├── data
│   │   ├── normal_dir
│   │   │   └── .gitkeep
│   │   ├── normal_file.txt
│   │   ├── special_dir  !@#$%^&()_+-=;',
│   │   │   └── .gitkeep
│   │   └── special_file  !@#$%^&()_+-=;',.txt
│   ├── etcd
│   │   ├── ca-key.pem
│   │   ├── ca.pem
│   │   ├── client-key.pem
│   │   ├── client.pem
│   │   ├── docker-compose-cluster.yml
│   │   ├── docker-compose-standalone-tls.yml
│   │   ├── docker-compose-standalone.yml
│   │   ├── server-key.pem
│   │   └── server.pem
│   ├── ftp
│   │   └── docker-compose-vsftpd.yml
│   ├── hdfs
│   │   ├── azurite-azblob-core-site.xml
│   │   ├── docker-compose-hdfs-cluster.yml
│   │   ├── gcs-core-site.xml
│   │   ├── hdfs-site.xml
│   │   └── minio-s3-core-site.xml
│   ├── http
│   │   ├── Caddyfile
│   │   ├── docker-compose-caddy.yml
│   │   ├── docker-compose-nginx.yml
│   │   └── nginx.conf
│   ├── libsql
│   │   ├── docker-compose-auth.yml
│   │   └── docker-compose.yml
│   ├── memcached
│   │   ├── docker-compose-memcached-with-auth.yml
│   │   └── docker-compose-memcached.yml
│   ├── mongodb
│   │   ├── docker-compose-basic-auth.yml
│   │   └── docker-compose-no-auth.yml
│   ├── mysql
│   │   ├── docker-compose.yml
│   │   └── init.sql
│   ├── postgresql
│   │   ├── docker-compose.yml
│   │   └── init.sql
│   ├── redis
│   │   ├── docker-compose-dragonfly.yml
│   │   ├── docker-compose-kvrocks.yml
│   │   ├── docker-compose-redis-cluster-tls.yml
│   │   ├── docker-compose-redis-cluster.yml
│   │   ├── docker-compose-redis-tls.yml
│   │   ├── docker-compose-redis.yml
│   │   └── ssl
│   │       ├── .gitignore
│   │       ├── ca.crt
│   │       ├── ca.key
│   │       ├── ca.srl
│   │       ├── README.md
│   │       ├── redis.crt
│   │       ├── redis.key
│   │       └── req.conf
│   ├── s3
│   │   ├── docker-compose-ceph-rados.yml
│   │   └── docker-compose-minio.yml
│   ├── seafile
│   │   └── docker-compose-seafile.yml
│   ├── sftp
│   │   ├── change_root_dir.sh
│   │   ├── docker-compose-sftp-with-default-root.yml
│   │   ├── docker-compose-sftp.yml
│   │   ├── health-check.sh
│   │   ├── test_ssh_key
│   │   └── test_ssh_key.pub
│   ├── sqlite
│   │   └── data.sql
│   ├── swift
│   │   ├── docker-compose-ceph-rados.yml
│   │   └── docker-compose-swift.yml
│   ├── tikv
│   │   ├── gen_cert.sh
│   │   ├── pd-tls.toml
│   │   ├── pd.toml
│   │   ├── ssl
│   │   │   ├── ca-key.pem
│   │   │   ├── ca.pem
│   │   │   ├── client-key.pem
│   │   │   ├── client.pem
│   │   │   ├── pd-server-key.pem
│   │   │   ├── pd-server.pem
│   │   │   ├── tikv-server-key.pem
│   │   │   └── tikv-server.pem
│   │   ├── tikv-tls.toml
│   │   └── tikv.toml
│   ├── webdav
│   │   ├── config
│   │   │   └── nginx
│   │   │       └── http.conf
│   │   ├── docker-compose-webdav-jfrog.yml
│   │   ├── docker-compose-webdav-nextcloud.yml
│   │   ├── docker-compose-webdav-owncloud.yml
│   │   ├── docker-compose-webdav-with-auth.yml
│   │   ├── docker-compose-webdav-with-empty-passwd.yml
│   │   ├── docker-compose-webdav.yml
│   │   └── health-check-nextcloud.sh
│   └── webhdfs
│       └── docker-compose-webhdfs.yml
├── justfile
├── LICENSE
├── licenserc.toml
├── NOTICE
├── README.md
├── rust-toolchain.toml
├── rustfmt.toml
└── scripts
    ├── constants.py
    ├── dependencies.py
    ├── merge_local_staging.py
    ├── README.md
    ├── verify.py
    └── workspace.py
```

# Files

--------------------------------------------------------------------------------
/core/core/src/types/operator/operator.rs:
--------------------------------------------------------------------------------

```rust
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

use std::future::Future;

use futures::Stream;
use futures::StreamExt;
use futures::TryStreamExt;

use crate::operator_futures::*;
use crate::raw::oio::DeleteDyn;
use crate::raw::*;
use crate::types::delete::Deleter;
use crate::*;

/// The `Operator` serves as the entry point for all public asynchronous APIs.
///
/// For more details about the `Operator`, refer to the [`concepts`][crate::docs::concepts] section.
///
/// All cloned `Operator` instances share the same internal state, such as
/// `HttpClient` and `Runtime`. Some layers may modify the internal state of
/// the `Operator` too like inject logging and metrics for `HttpClient`.
///
/// ## Build
///
/// Users can initialize an `Operator` through the following methods:
///
/// - [`Operator::new`]: Creates an operator using a [`services`] builder, such as [`services::Memory`].
/// - [`Operator::from_config`]: Creates an operator using a [`services`] configuration, such as [`services::MemoryConfig`].
/// - [`Operator::from_iter`]: Creates an operator from an iterator of configuration key-value pairs.
///
/// ```
/// # use anyhow::Result;
/// use opendal_core::services::Memory;
/// use opendal_core::Operator;
/// async fn test() -> Result<()> {
///     // Build an `Operator` to start operating the storage.
///     let _: Operator = Operator::new(Memory::default())?.finish();
///
///     Ok(())
/// }
/// ```
///
/// ## Layer
///
/// After the operator is built, users can add the layers they need on top of it.
///
/// OpenDAL offers various layers for users to choose from. Visit [`layers`] for further details.
///
/// Please note that `Layer` can modify internal contexts such as `HttpClient`
/// and `Runtime` for all clones of given operator. Therefore, it is recommended
/// to add layers before interacting with the storage. Adding or duplicating
/// layers after accessing the storage may result in unexpected behavior.
///
/// ```
/// use opendal_core::layers::HttpClientLayer;
/// use opendal_core::raw::HttpClient;
/// use opendal_core::services::Memory;
/// use opendal_core::Operator;
/// use opendal_core::Result;
///
/// async fn test() -> Result<()> {
///     let op: Operator = Operator::new(Memory::default())?.finish();
///
///     // OpenDAL will replace the default HTTP client now.
///     let client = HttpClient::new()?;
///     let op = op.layer(HttpClientLayer::new(client));
///
///     Ok(())
/// }
/// ```
///
/// ## Operate
///
/// After the operator is built and the layers are added, users can start operating the storage.
///
/// The operator is `Send`, `Sync`, and `Clone`. It has no internal state, and all APIs only take
/// a `&self` reference, making it safe to share the operator across threads.
///
/// Operator provides a consistent API pattern for data operations. For reading operations, it exposes:
///
/// - [`Operator::read`]: Executes a read operation.
/// - [`Operator::read_with`]: Executes a read operation with additional options using the builder pattern.
/// - [`Operator::read_options`]: Executes a read operation with extra options provided via a [`options::ReadOptions`] struct.
/// - [`Operator::reader`]: Creates a reader for streaming data, allowing for flexible access.
/// - [`Operator::reader_with`]: Creates a reader with advanced options using the builder pattern.
/// - [`Operator::reader_options`]: Creates a reader with extra options provided via a [`options::ReadOptions`] struct.
///
/// The [`Reader`] created by [`Operator`] supports custom read control methods and can be converted
/// into [`futures::AsyncRead`] or [`futures::Stream`] for broader ecosystem compatibility.
///
/// ```no_run
/// use opendal_core::options;
/// use opendal_core::services;
/// use opendal_core::Operator;
/// use opendal_core::Result;
///
/// #[tokio::main]
/// async fn main() -> Result<()> {
///     // Pick a builder and configure it.
///     let builder = services::Memory::default();
///
///     // Init an operator
///     let op = Operator::new(builder)?.finish();
///
///     // Fetch this file's metadata
///     let meta = op.stat("hello.txt").await?;
///     let length = meta.content_length();
///
///     // Read data from `hello.txt` with options.
///     let bs = op
///         .read_with("hello.txt")
///         .range(0..8 * 1024 * 1024)
///         .chunk(1024 * 1024)
///         .concurrent(4)
///         .await?;
///
///     // The same to:
///     let bs = op
///         .read_options("hello.txt", options::ReadOptions {
///             range: (0..8 * 1024 * 1024).into(),
///             chunk: Some(1024 * 1024),
///             concurrent: 4,
///             ..Default::default()
///         })
///         .await?;
///
///     Ok(())
/// }
/// ```
#[derive(Clone, Debug)]
pub struct Operator {
    // accessor is what Operator delegates for
    accessor: Accessor,
}

/// # Operator basic API.
impl Operator {
    /// Fetch the internal accessor.
    pub fn inner(&self) -> &Accessor {
        &self.accessor
    }

    /// Convert inner accessor into operator.
    pub fn from_inner(accessor: Accessor) -> Self {
        Self { accessor }
    }

    /// Convert operator into inner accessor.
    pub fn into_inner(self) -> Accessor {
        self.accessor
    }

    /// Get information of underlying accessor.
    ///
    /// # Examples
    ///
    /// ```
    /// # use std::sync::Arc;
    /// # use anyhow::Result;
    /// use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let info = op.info();
    /// # Ok(())
    /// # }
    /// ```
    pub fn info(&self) -> OperatorInfo {
        OperatorInfo::new(self.accessor.info())
    }

    /// Get the executor used by current operator.
    pub fn executor(&self) -> Executor {
        self.accessor.info().executor()
    }

    /// Update executor for the context.
    ///
    /// All cloned `Operator` instances share the same internal state, such as
    /// `HttpClient` and `Runtime`. Some layers may modify the internal state of
    /// the `Operator` too like inject logging and metrics for `HttpClient`.
    ///
    /// # Note
    ///
    /// Tasks must be forwarded to the old executor after the update. Otherwise, features such as retry, timeout, and metrics may not function properly.
    pub fn update_executor(&self, f: impl FnOnce(Executor) -> Executor) {
        self.accessor.info().update_executor(f);
    }
}

/// # Operator async API.
impl Operator {
    /// Check if this operator can work correctly.
    ///
    /// We will send a `list` request to path and return any errors we met.
    ///
    /// ```
    /// # use std::sync::Arc;
    /// # use anyhow::Result;
    /// use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.check().await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn check(&self) -> Result<()> {
        let mut ds = self.lister_with("/").limit(1).await?;

        match ds.next().await {
            Some(Err(e)) if e.kind() != ErrorKind::NotFound => Err(e),
            _ => Ok(()),
        }
    }

    /// Retrieve the metadata for the specified path.
    ///
    /// # Notes
    ///
    /// ## Extra Options
    ///
    /// [`Operator::stat`] is a wrapper around [`Operator::stat_with`] that uses no additional options.
    /// To specify extra options such as `if_match` and `if_none_match`, please use [`Operator::stat_with`] instead.
    ///
    /// # Examples
    ///
    /// ## Check if file exists
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// # use opendal_core::Operator;
    /// use opendal_core::ErrorKind;
    /// #
    /// # async fn test(op: Operator) -> Result<()> {
    /// if let Err(e) = op.stat("test").await {
    ///     if e.kind() == ErrorKind::NotFound {
    ///         println!("file not exist")
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn stat(&self, path: &str) -> Result<Metadata> {
        self.stat_with(path).await
    }

    /// Retrieve the metadata of the specified path with additional options.
    ///
    /// # Options
    ///
    /// Check [`options::StatOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// ## Get metadata while `ETag` matches
    ///
    /// `stat_with` will
    ///
    /// - return `Ok(metadata)` if `ETag` matches
    /// - return `Err(error)` and `error.kind() == ErrorKind::ConditionNotMatch` if file exists but
    ///   `ETag` mismatch
    /// - return `Err(err)` if other errors occur, for example, `NotFound`.
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// # use opendal_core::Operator;
    /// use opendal_core::ErrorKind;
    /// #
    /// # async fn test(op: Operator) -> Result<()> {
    /// if let Err(e) = op.stat_with("test").if_match("<etag>").await {
    ///     if e.kind() == ErrorKind::ConditionNotMatch {
    ///         println!("file exists, but etag mismatch")
    ///     }
    ///     if e.kind() == ErrorKind::NotFound {
    ///         println!("file not exist")
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn stat_with(&self, path: &str) -> FutureStat<impl Future<Output = Result<Metadata>>> {
        let path = normalize_path(path);
        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::StatOptions::default(),
            Self::stat_inner,
        )
    }

    /// Retrieve the metadata of the specified path with additional options.
    ///
    /// # Examples
    ///
    /// ## Get metadata while `ETag` matches
    ///
    /// `stat_with` will
    ///
    /// - return `Ok(metadata)` if `ETag` matches
    /// - return `Err(error)` and `error.kind() == ErrorKind::ConditionNotMatch` if file exists but
    ///   `ETag` mismatch
    /// - return `Err(err)` if other errors occur, for example, `NotFound`.
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// # use opendal_core::Operator;
    /// use opendal_core::options;
    /// use opendal_core::ErrorKind;
    /// #
    /// # async fn test(op: Operator) -> Result<()> {
    /// let res = op
    ///     .stat_options("test", options::StatOptions {
    ///         if_match: Some("<etag>".to_string()),
    ///         ..Default::default()
    ///     })
    ///     .await;
    /// if let Err(e) = res {
    ///     if e.kind() == ErrorKind::ConditionNotMatch {
    ///         println!("file exists, but etag mismatch")
    ///     }
    ///     if e.kind() == ErrorKind::NotFound {
    ///         println!("file not exist")
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn stat_options(&self, path: &str, opts: options::StatOptions) -> Result<Metadata> {
        let path = normalize_path(path);
        Self::stat_inner(self.accessor.clone(), path, opts).await
    }

    #[inline]
    async fn stat_inner(
        acc: Accessor,
        path: String,
        opts: options::StatOptions,
    ) -> Result<Metadata> {
        let rp = acc.stat(&path, opts.into()).await?;
        Ok(rp.into_metadata())
    }

    /// Check whether this path exists.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use futures::io;
    /// use opendal_core::Operator;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let _ = op.exists("test").await?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub async fn exists(&self, path: &str) -> Result<bool> {
        let r = self.stat(path).await;
        match r {
            Ok(_) => Ok(true),
            Err(err) if err.kind() == ErrorKind::NotFound => Ok(false),
            Err(err) => Err(err),
        }
    }

    /// Create a directory at the specified path.
    ///
    /// # Notes
    ///
    /// To specify that a path is a directory, you must include a trailing slash (/).
    /// Omitting the trailing slash may cause OpenDAL to return a `NotADirectory` error.
    ///
    /// # Behavior
    ///
    /// - Creating a directory that already exists will succeed.
    /// - Directory creation is always recursive, functioning like `mkdir -p`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.create_dir("path/to/dir/").await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn create_dir(&self, path: &str) -> Result<()> {
        let path = normalize_path(path);

        if !validate_path(&path, EntryMode::DIR) {
            return Err(Error::new(
                ErrorKind::NotADirectory,
                "the path trying to create should end with `/`",
            )
            .with_operation("create_dir")
            .with_context("service", self.inner().info().scheme())
            .with_context("path", &path));
        }

        self.inner().create_dir(&path, OpCreateDir::new()).await?;

        Ok(())
    }

    /// Read the entire file into bytes from given path.
    ///
    /// # Notes
    ///
    /// ## Additional Options
    ///
    /// [`Operator::read`] is a simplified method that does not support additional options. To access features like `range` and `if_match`, please use [`Operator::read_with`] or [`Operator::read_options`] instead.
    ///
    /// ## Streaming Read
    ///
    /// This function reads all content into memory at once. For more precise memory management or to read big file lazily, please use [`Operator::reader`].
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # use futures::TryStreamExt;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let bs = op.read("path/to/file").await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn read(&self, path: &str) -> Result<Buffer> {
        self.read_options(path, options::ReadOptions::default())
            .await
    }

    /// Read the entire file into bytes from given path with additional options.
    ///
    /// # Notes
    ///
    /// ## Streaming Read
    ///
    /// This function reads all content into memory at once. For more precise memory management or to read big file lazily, please use [`Operator::reader`].
    ///
    /// # Options
    ///
    /// Visit [`options::ReadOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Read the first 10 bytes of a file:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let bs = op.read_with("path/to/file").range(0..10).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn read_with(&self, path: &str) -> FutureRead<impl Future<Output = Result<Buffer>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::ReadOptions::default(),
            Self::read_inner,
        )
    }

    /// Read the entire file into bytes from given path with additional options.
    ///
    /// # Notes
    ///
    /// ## Streaming Read
    ///
    /// This function reads all content into memory at once. For more precise memory management or to read big file lazily, please use [`Operator::reader`].
    ///
    /// # Examples
    ///
    /// Read the first 10 bytes of a file:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use opendal_core::options;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let bs = op
    ///     .read_options("path/to/file", options::ReadOptions {
    ///         range: (0..10).into(),
    ///         ..Default::default()
    ///     })
    ///     .await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn read_options(&self, path: &str, opts: options::ReadOptions) -> Result<Buffer> {
        let path = normalize_path(path);
        Self::read_inner(self.inner().clone(), path, opts).await
    }

    #[inline]
    async fn read_inner(acc: Accessor, path: String, opts: options::ReadOptions) -> Result<Buffer> {
        if !validate_path(&path, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "read path is a directory")
                    .with_operation("read")
                    .with_context("service", acc.info().scheme())
                    .with_context("path", &path),
            );
        }

        let (args, opts) = opts.into();
        let range = args.range();
        let context = ReadContext::new(acc, path, args, opts);
        let r = Reader::new(context);
        let buf = r.read(range.to_range()).await?;
        Ok(buf)
    }

    /// Create a new reader of given path.
    ///
    /// # Notes
    ///
    /// ## Extra Options
    ///
    /// [`Operator::reader`] is a simplified method without any options. To use additional options such as `concurrent` or `if_match`, please use [`Operator::reader_with`] or [`Operator::reader_options`] instead.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # use futures::TryStreamExt;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let r = op.reader("path/to/file").await?;
    /// // Read the first 10 bytes of the file
    /// let data = r.read(0..10).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn reader(&self, path: &str) -> Result<Reader> {
        self.reader_with(path).await
    }

    /// Create a new reader of given path with additional options.
    ///
    /// # Options
    ///
    /// Visit [`options::ReaderOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Create a reader with a specific version ID:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let r = op.reader_with("path/to/file").version("version_id").await?;
    /// // Read the first 10 bytes of the file
    /// let data = r.read(0..10).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn reader_with(&self, path: &str) -> FutureReader<impl Future<Output = Result<Reader>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::ReaderOptions::default(),
            Self::reader_inner,
        )
    }

    /// Create a new reader of given path with additional options.
    ///
    /// # Examples
    ///
    /// Create a reader with a specific version ID:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use opendal_core::options;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let r = op
    ///     .reader_options("path/to/file", options::ReaderOptions {
    ///         version: Some("version_id".to_string()),
    ///         ..Default::default()
    ///     })
    ///     .await?;
    /// // Read the first 10 bytes of the file
    /// let data = r.read(0..10).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn reader_options(&self, path: &str, opts: options::ReaderOptions) -> Result<Reader> {
        let path = normalize_path(path);
        Self::reader_inner(self.inner().clone(), path, opts).await
    }

    /// Allow this unused async since we don't want
    /// to change our public API.
    #[allow(clippy::unused_async)]
    #[inline]
    async fn reader_inner(
        acc: Accessor,
        path: String,
        options: options::ReaderOptions,
    ) -> Result<Reader> {
        if !validate_path(&path, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "read path is a directory")
                    .with_operation("Operator::reader")
                    .with_context("service", acc.info().scheme())
                    .with_context("path", path),
            );
        }

        let (args, opts) = options.into();
        let context = ReadContext::new(acc, path, args, opts);
        Ok(Reader::new(context))
    }

    /// Write all data to the specified path at once.
    ///
    /// # Notes
    ///
    /// Visit [`performance::concurrent_write`][crate::docs::performance::concurrent_write] for more details on concurrent writes.
    ///
    /// ## Extra Options
    ///
    /// [`Operator::write`] is a simplified method that does not include additional options.
    /// For advanced features such as `chunk` and `concurrent`, use [`Operator::write_with`] or [`Operator::write_options`] instead.
    ///
    /// ## Streaming Write
    ///
    /// This method executes a single bulk write operation. For more precise memory management
    /// or to write data in a streaming fashion, use [`Operator::writer`] instead.
    ///
    /// ## Multipart Uploads
    ///
    /// OpenDAL offers multipart upload capabilities through the [`Writer`] abstraction,
    /// automatically managing all upload details for you. You can fine-tune the upload process
    /// by adjusting the `chunk` size and the number of `concurrent` operations using [`Operator::writer_with`].
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # use futures::StreamExt;
    /// # use futures::SinkExt;
    /// use bytes::Bytes;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.write("path/to/file", vec![0; 4096]).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn write(&self, path: &str, bs: impl Into<Buffer>) -> Result<Metadata> {
        let bs = bs.into();
        self.write_with(path, bs).await
    }

    /// Write all data to the specified path at once with additional options.
    ///
    /// # Notes
    ///
    /// Visit [`performance::concurrent_write`][crate::docs::performance::concurrent_write] for more details on concurrent writes.
    ///
    /// ## Streaming Write
    ///
    /// This method executes a single bulk write operation. For more precise memory management
    /// or to write data in a streaming fashion, use [`Operator::writer`] instead.
    ///
    /// ## Multipart Uploads
    ///
    /// OpenDAL offers multipart upload capabilities through the [`Writer`] abstraction,
    /// automatically managing all upload details for you. You can fine-tune the upload process
    /// by adjusting the `chunk` size and the number of `concurrent` operations using [`Operator::writer_with`].
    ///
    /// # Options
    ///
    /// Visit [`options::WriteOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Write data to a file only when it does not already exist:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use bytes::Bytes;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let _ = op
    ///     .write_with("path/to/file", vec![0; 4096])
    ///     .if_not_exists(true)
    ///     .await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn write_with(
        &self,
        path: &str,
        bs: impl Into<Buffer>,
    ) -> FutureWrite<impl Future<Output = Result<Metadata>>> {
        let path = normalize_path(path);
        let bs = bs.into();

        OperatorFuture::new(
            self.inner().clone(),
            path,
            (options::WriteOptions::default(), bs),
            |inner, path, (opts, bs)| Self::write_inner(inner, path, bs, opts),
        )
    }

    /// Write all data to the specified path at once with additional options.
    ///
    /// # Notes
    ///
    /// Visit [`performance::concurrent_write`][crate::docs::performance::concurrent_write] for more details on concurrent writes.
    ///
    /// ## Streaming Write
    ///
    /// This method executes a single bulk write operation. For more precise memory management
    /// or to write data in a streaming fashion, use [`Operator::writer`] instead.
    ///
    /// ## Multipart Uploads
    ///
    /// OpenDAL offers multipart upload capabilities through the [`Writer`] abstraction,
    /// automatically managing all upload details for you. You can fine-tune the upload process
    /// by adjusting the `chunk` size and the number of `concurrent` operations using [`Operator::writer_with`].
    ///
    /// # Examples
    ///
    /// Write data to a file only when it does not already exist:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use opendal_core::options;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let _ = op
    ///     .write_options("path/to/file", vec![0; 4096], options::WriteOptions {
    ///         if_not_exists: true,
    ///         ..Default::default()
    ///     })
    ///     .await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn write_options(
        &self,
        path: &str,
        bs: impl Into<Buffer>,
        opts: options::WriteOptions,
    ) -> Result<Metadata> {
        let path = normalize_path(path);
        Self::write_inner(self.inner().clone(), path, bs.into(), opts).await
    }

    #[inline]
    async fn write_inner(
        acc: Accessor,
        path: String,
        bs: Buffer,
        opts: options::WriteOptions,
    ) -> Result<Metadata> {
        if !validate_path(&path, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "write path is a directory")
                    .with_operation("Operator::write")
                    .with_context("service", acc.info().scheme())
                    .with_context("path", &path),
            );
        }

        let (args, opts) = opts.into();

        let context = WriteContext::new(acc, path, args, opts);
        let mut w = Writer::new(context).await?;
        w.write(bs).await?;
        w.close().await
    }

    /// Create a new writer of given path.
    ///
    /// # Notes
    ///
    /// ## Writer Features
    ///
    /// The writer provides several powerful capabilities:
    /// - Streaming writes for continuous data transfer
    /// - Automatic multipart upload handling
    /// - Memory-efficient chunk-based writing
    ///
    /// ## Extra Options
    ///
    /// [`Operator::writer`] is a simplified version that does not include additional options.
    /// For advanced features such as `chunk` and `concurrent`, use [`Operator::writer_with`] or [`Operator::writer_options`] instead.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use bytes::Bytes;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut w = op.writer("path/to/file").await?;
    /// w.write(vec![0; 4096]).await?;
    /// w.write(vec![1; 4096]).await?;
    /// w.close().await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn writer(&self, path: &str) -> Result<Writer> {
        self.writer_with(path).await
    }

    /// Create a new writer of given path with additional options.
    ///
    /// # Notes
    ///
    /// ## Writer Features
    ///
    /// The writer provides several powerful capabilities:
    /// - Streaming writes for continuous data transfer
    /// - Automatic multipart upload handling
    /// - Memory-efficient chunk-based writing
    ///
    /// ## Chunk Size Handling
    ///
    /// Storage services often have specific requirements for chunk sizes:
    /// - Services like `s3` may return `EntityTooSmall` errors for undersized chunks
    /// - Using small chunks in cloud storage services can lead to increased costs
    ///
    /// OpenDAL automatically determines optimal chunk sizes based on the service's
    /// [Capability](crate::types::Capability). However, you can override this by explicitly
    /// setting the `chunk` parameter.
    ///
    /// Visit [`performance::concurrent_write`][crate::docs::performance::concurrent_write] for more details on concurrent writes.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use bytes::Bytes;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut w = op
    ///     .writer_with("path/to/file")
    ///     .chunk(4 * 1024 * 1024)
    ///     .concurrent(8)
    ///     .await?;
    /// w.write(vec![0; 4096]).await?;
    /// w.write(vec![1; 4096]).await?;
    /// w.close().await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn writer_with(&self, path: &str) -> FutureWriter<impl Future<Output = Result<Writer>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::WriteOptions::default(),
            Self::writer_inner,
        )
    }

    /// Create a new writer of given path with additional options.
    ///
    /// # Notes
    ///
    /// ## Writer Features
    ///
    /// The writer provides several powerful capabilities:
    /// - Streaming writes for continuous data transfer
    /// - Automatic multipart upload handling
    /// - Memory-efficient chunk-based writing
    ///
    /// ## Chunk Size Handling
    ///
    /// Storage services often have specific requirements for chunk sizes:
    /// - Services like `s3` may return `EntityTooSmall` errors for undersized chunks
    /// - Using small chunks in cloud storage services can lead to increased costs
    ///
    /// OpenDAL automatically determines optimal chunk sizes based on the service's
    /// [Capability](crate::types::Capability). However, you can override this by explicitly
    /// setting the `chunk` parameter.
    ///
    /// Visit [`performance::concurrent_write`][crate::docs::performance::concurrent_write] for more details on concurrent writes.
    ///
    /// # Examples
    ///
    /// Write data to a file in 4MiB chunk size and at 8 concurrency:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use bytes::Bytes;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut w = op
    ///     .writer_with("path/to/file")
    ///     .chunk(4 * 1024 * 1024)
    ///     .concurrent(8)
    ///     .await?;
    /// w.write(vec![0; 4096]).await?;
    /// w.write(vec![1; 4096]).await?;
    /// w.close().await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn writer_options(&self, path: &str, opts: options::WriteOptions) -> Result<Writer> {
        let path = normalize_path(path);
        Self::writer_inner(self.inner().clone(), path, opts).await
    }

    #[inline]
    async fn writer_inner(
        acc: Accessor,
        path: String,
        opts: options::WriteOptions,
    ) -> Result<Writer> {
        if !validate_path(&path, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "write path is a directory")
                    .with_operation("Operator::writer")
                    .with_context("service", acc.info().scheme())
                    .with_context("path", &path),
            );
        }

        let (args, opts) = opts.into();
        let context = WriteContext::new(acc, path, args, opts);
        let w = Writer::new(context).await?;
        Ok(w)
    }

    /// Copy a file from `from` to `to`.
    ///
    /// # Notes
    ///
    /// - `from` and `to` must be a file.
    /// - `to` will be overwritten if it exists.
    /// - If `from` and `to` are the same,  an `IsSameFile` error will occur.
    /// - `copy` is idempotent. For same `from` and `to` input, the result will be the same.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.copy("path/to/file", "path/to/file2").await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn copy(&self, from: &str, to: &str) -> Result<()> {
        let from = normalize_path(from);

        if !validate_path(&from, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "from path is a directory")
                    .with_operation("Operator::copy")
                    .with_context("service", self.info().scheme())
                    .with_context("from", from),
            );
        }

        let to = normalize_path(to);

        if !validate_path(&to, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "to path is a directory")
                    .with_operation("Operator::copy")
                    .with_context("service", self.info().scheme())
                    .with_context("to", to),
            );
        }

        if from == to {
            return Err(
                Error::new(ErrorKind::IsSameFile, "from and to paths are same")
                    .with_operation("Operator::copy")
                    .with_context("service", self.info().scheme())
                    .with_context("from", from)
                    .with_context("to", to),
            );
        }

        self.inner().copy(&from, &to, OpCopy::new()).await?;

        Ok(())
    }

    /// Copy a file from `from` to `to` with additional options.
    ///
    /// # Notes
    ///
    /// - `from` and `to` must be a file.
    /// - If `from` and `to` are the same, an `IsSameFile` error will occur.
    /// - `copy` is idempotent. For same `from` and `to` input, the result will be the same.
    ///
    /// # Options
    ///
    /// Visit [`options::CopyOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Copy a file only if the destination doesn't exist:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.copy_with("path/to/file", "path/to/file2")
    ///     .if_not_exists(true)
    ///     .await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn copy_with(&self, from: &str, to: &str) -> FutureCopy<impl Future<Output = Result<()>>> {
        let from = normalize_path(from);
        let to = normalize_path(to);

        OperatorFuture::new(
            self.inner().clone(),
            from,
            (options::CopyOptions::default(), to),
            Self::copy_inner,
        )
    }

    /// Copy a file from `from` to `to` with additional options.
    ///
    /// # Notes
    ///
    /// - `from` and `to` must be a file.
    /// - If `from` and `to` are the same, an `IsSameFile` error will occur.
    /// - `copy` is idempotent. For same `from` and `to` input, the result will be the same.
    ///
    /// # Options
    ///
    /// Check [`options::CopyOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Copy a file only if the destination doesn't exist:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// # use opendal_core::options::CopyOptions;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut opts = CopyOptions::default();
    /// opts.if_not_exists = true;
    /// op.copy_options("path/to/file", "path/to/file2", opts).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn copy_options(
        &self,
        from: &str,
        to: &str,
        opts: impl Into<options::CopyOptions>,
    ) -> Result<()> {
        let from = normalize_path(from);
        let to = normalize_path(to);
        let opts = opts.into();

        Self::copy_inner(self.inner().clone(), from, (opts, to)).await
    }

    async fn copy_inner(
        acc: Accessor,
        from: String,
        (opts, to): (options::CopyOptions, String),
    ) -> Result<()> {
        if !validate_path(&from, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "from path is a directory")
                    .with_operation("Operator::copy")
                    .with_context("service", acc.info().scheme())
                    .with_context("from", from),
            );
        }

        if !validate_path(&to, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "to path is a directory")
                    .with_operation("Operator::copy")
                    .with_context("service", acc.info().scheme())
                    .with_context("to", to),
            );
        }

        if from == to {
            return Err(
                Error::new(ErrorKind::IsSameFile, "from and to paths are same")
                    .with_operation("Operator::copy")
                    .with_context("service", acc.info().scheme())
                    .with_context("from", &from)
                    .with_context("to", &to),
            );
        }

        let mut op = OpCopy::new();
        if opts.if_not_exists {
            op = op.with_if_not_exists(true);
        }

        acc.copy(&from, &to, op).await.map(|_| ())
    }

    /// Rename a file from `from` to `to`.
    ///
    /// # Notes
    ///
    /// - `from` and `to` must be a file.
    /// - `to` will be overwritten if it exists.
    /// - If `from` and `to` are the same, an `IsSameFile` error will occur.
    ///
    /// # Examples
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.rename("path/to/file", "path/to/file2").await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn rename(&self, from: &str, to: &str) -> Result<()> {
        let from = normalize_path(from);

        if !validate_path(&from, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "from path is a directory")
                    .with_operation("Operator::move_")
                    .with_context("service", self.info().scheme())
                    .with_context("from", from),
            );
        }

        let to = normalize_path(to);

        if !validate_path(&to, EntryMode::FILE) {
            return Err(
                Error::new(ErrorKind::IsADirectory, "to path is a directory")
                    .with_operation("Operator::move_")
                    .with_context("service", self.info().scheme())
                    .with_context("to", to),
            );
        }

        if from == to {
            return Err(
                Error::new(ErrorKind::IsSameFile, "from and to paths are same")
                    .with_operation("Operator::move_")
                    .with_context("service", self.info().scheme())
                    .with_context("from", from)
                    .with_context("to", to),
            );
        }

        self.inner().rename(&from, &to, OpRename::new()).await?;

        Ok(())
    }

    /// Delete the given path.
    ///
    /// # Notes
    ///
    /// - Deleting a file that does not exist won't return errors.
    ///
    /// # Examples
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// # use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.delete("test").await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn delete(&self, path: &str) -> Result<()> {
        self.delete_with(path).await
    }

    /// Delete the given path with additional options.
    ///
    /// # Notes
    ///
    /// - Deleting a file that does not exist won't return errors.
    ///
    /// # Options
    ///
    /// Visit [`options::DeleteOptions`] for all available options.
    ///
    /// # Examples
    ///
    /// Delete a specific version of a file:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    ///
    /// # async fn test(op: Operator, version: &str) -> Result<()> {
    /// op.delete_with("path/to/file").version(version).await?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn delete_with(&self, path: &str) -> FutureDelete<impl Future<Output = Result<()>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::DeleteOptions::default(),
            Self::delete_inner,
        )
    }

    /// Delete the given path with additional options.
    ///
    /// # Notes
    ///
    /// - Deleting a file that does not exist won't return errors.
    ///
    /// # Examples
    ///
    /// Delete a specific version of a file:
    ///
    /// ```
    /// # use opendal_core::Result;
    /// # use opendal_core::Operator;
    /// use opendal_core::options;
    ///
    /// # async fn test(op: Operator, version: &str) -> Result<()> {
    /// op.delete_options("path/to/file", options::DeleteOptions {
    ///     version: Some(version.to_string()),
    ///     ..Default::default()
    /// })
    /// .await?;
    /// # Ok(())
    /// # }
    /// ```
    pub async fn delete_options(&self, path: &str, opts: options::DeleteOptions) -> Result<()> {
        let path = normalize_path(path);
        Self::delete_inner(self.inner().clone(), path, opts).await
    }

    async fn delete_inner(acc: Accessor, path: String, opts: options::DeleteOptions) -> Result<()> {
        let (_, mut deleter) = acc.delete_dyn().await?;
        let args = opts.into();
        deleter.delete_dyn(&path, args).await?;
        deleter.close_dyn().await?;
        Ok(())
    }

    /// Delete an infallible iterator of paths.
    ///
    /// Also see:
    ///
    /// - [`Operator::delete_try_iter`]: delete a fallible iterator of paths.
    /// - [`Operator::delete_stream`]: delete an infallible stream of paths.
    /// - [`Operator::delete_try_stream`]: delete a fallible stream of paths.
    pub async fn delete_iter<I, D>(&self, iter: I) -> Result<()>
    where
        I: IntoIterator<Item = D>,
        D: IntoDeleteInput,
    {
        let mut deleter = self.deleter().await?;
        deleter.delete_iter(iter).await?;
        deleter.close().await?;
        Ok(())
    }

    /// Delete a fallible iterator of paths.
    ///
    /// Also see:
    ///
    /// - [`Operator::delete_iter`]: delete an infallible iterator of paths.
    /// - [`Operator::delete_stream`]: delete an infallible stream of paths.
    /// - [`Operator::delete_try_stream`]: delete a fallible stream of paths.
    pub async fn delete_try_iter<I, D>(&self, try_iter: I) -> Result<()>
    where
        I: IntoIterator<Item = Result<D>>,
        D: IntoDeleteInput,
    {
        let mut deleter = self.deleter().await?;
        deleter.delete_try_iter(try_iter).await?;
        deleter.close().await?;
        Ok(())
    }

    /// Delete an infallible stream of paths.
    ///
    /// Also see:
    ///
    /// - [`Operator::delete_iter`]: delete an infallible iterator of paths.
    /// - [`Operator::delete_try_iter`]: delete a fallible iterator of paths.
    /// - [`Operator::delete_try_stream`]: delete a fallible stream of paths.
    pub async fn delete_stream<S, D>(&self, stream: S) -> Result<()>
    where
        S: Stream<Item = D>,
        D: IntoDeleteInput,
    {
        let mut deleter = self.deleter().await?;
        deleter.delete_stream(stream).await?;
        deleter.close().await?;
        Ok(())
    }

    /// Delete a fallible stream of paths.
    ///
    /// Also see:
    ///
    /// - [`Operator::delete_iter`]: delete an infallible iterator of paths.
    /// - [`Operator::delete_try_iter`]: delete a fallible iterator of paths.
    /// - [`Operator::delete_stream`]: delete an infallible stream of paths.
    pub async fn delete_try_stream<S, D>(&self, try_stream: S) -> Result<()>
    where
        S: Stream<Item = Result<D>>,
        D: IntoDeleteInput,
    {
        let mut deleter = self.deleter().await?;
        deleter.delete_try_stream(try_stream).await?;
        deleter.close().await?;
        Ok(())
    }

    /// Create a [`Deleter`] to continuously remove content from storage.
    ///
    /// It leverages batch deletion capabilities provided by storage services for efficient removal.
    ///
    /// Users can have more control over the deletion process by using [`Deleter`] directly.
    pub async fn deleter(&self) -> Result<Deleter> {
        Deleter::create(self.inner().clone()).await
    }

    /// Remove the path and all nested dirs and files recursively.
    ///
    /// # Deprecated
    ///
    /// This method is deprecated since v0.55.0. Use [`Operator::delete_with`] with
    /// `recursive(true)` instead.
    ///
    /// ## Migration Example
    ///
    /// Instead of:
    /// ```ignore
    /// op.remove_all("path/to/dir").await?;
    /// ```
    ///
    /// Use:
    /// ```ignore
    /// op.delete_with("path/to/dir").recursive(true).await?;
    /// ```
    ///
    /// # Notes
    ///
    /// If underlying services support delete in batch, we will use batch
    /// delete instead.
    ///
    /// # Examples
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// # use opendal_core::Operator;
    /// #
    /// # async fn test(op: Operator) -> Result<()> {
    /// op.remove_all("path/to/dir").await?;
    /// # Ok(())
    /// # }
    /// ```
    #[deprecated(
        since = "0.55.0",
        note = "Use `delete_with` with `recursive(true)` instead"
    )]
    pub async fn remove_all(&self, path: &str) -> Result<()> {
        self.delete_with(path).recursive(true).await
    }

    /// List entries whose paths start with the given prefix `path`.
    ///
    /// # Semantics
    ///
    /// - Listing is **prefix-based**. It does not require the parent directory to exist.
    /// - If `path` itself exists (file or dir), it will be returned as an entry in addition to any prefixed children.
    /// - If `path` is absent but deeper objects exist (e.g. `path/child`), the list succeeds and returns those prefixed entries instead of an error.
    ///
    /// ## Streaming List
    ///
    /// This function materializes the entire list into memory. For large listings, prefer [`Operator::lister`] to stream entries.
    ///
    /// # Examples
    ///
    /// This example will list all entries under the dir `path/to/dir/`.
    ///
    /// ```
    /// # use anyhow::Result;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut entries = op.list("path/to/dir/").await?;
    /// for entry in entries {
    ///     match entry.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file")
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir {}", entry.path())
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn list(&self, path: &str) -> Result<Vec<Entry>> {
        self.list_with(path).await
    }

    /// List entries whose paths start with the given prefix `path` with additional options.
    ///
    /// # Semantics
    ///
    /// Inherits the prefix semantics described in [`Operator::list`]: returns `path` itself if it exists and tolerates missing parents when prefixed objects exist.
    ///
    /// # Notes
    ///
    /// ## Streaming List
    ///
    /// This function materializes the entire list into memory. For large listings, prefer [`Operator::lister`] to stream entries.
    ///
    /// ## Options
    ///
    /// See [`options::ListOptions`] for the full set. Common knobs:
    /// - Traversal: `recursive` (default `false`) toggles depth-first listing under the prefix.
    /// - Pagination: `limit` and `start_after` tune page size and resume positions (backend dependent).
    /// - Versioning: `versions` / `deleted` ask versioned backends to return extra entries.
    ///
    /// # Examples
    ///
    /// This example will list all entries recursively under the prefix `path/to/prefix`.
    ///
    /// ```
    /// # use anyhow::Result;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut entries = op.list_with("path/to/prefix").recursive(true).await?;
    /// for entry in entries {
    ///     match entry.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file")
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir like start a new list via meta.path()")
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn list_with(&self, path: &str) -> FutureList<impl Future<Output = Result<Vec<Entry>>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::ListOptions::default(),
            Self::list_inner,
        )
    }

    /// List entries whose paths start with the given prefix `path` using explicit options.
    ///
    /// # Semantics
    ///
    /// Same prefix behavior as [`Operator::list`]: returns `path` itself if present and tolerates missing parents when prefixed objects exist.
    ///
    /// # Options
    ///
    /// Accepts [`options::ListOptions`] (see field docs for meaning).
    ///
    /// ## Streaming List
    ///
    /// Materializes the entire list; use [`Operator::lister`] to stream large result sets.
    ///
    /// # Examples
    ///
    /// This example will list all entries recursively under the prefix `path/to/prefix`.
    ///
    /// ```
    /// # use anyhow::Result;
    /// use opendal_core::options;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut entries = op
    ///     .list_options("path/to/prefix", options::ListOptions {
    ///         recursive: true,
    ///         ..Default::default()
    ///     })
    ///     .await?;
    /// for entry in entries {
    ///     match entry.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file")
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir like start a new list via meta.path()")
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn list_options(&self, path: &str, opts: options::ListOptions) -> Result<Vec<Entry>> {
        let path = normalize_path(path);
        Self::list_inner(self.inner().clone(), path, opts).await
    }

    #[inline]
    async fn list_inner(
        acc: Accessor,
        path: String,
        opts: options::ListOptions,
    ) -> Result<Vec<Entry>> {
        let args = opts.into();
        let lister = Lister::create(acc, &path, args).await?;
        lister.try_collect().await
    }

    /// Create a streaming lister for entries whose paths start with the given prefix `path`.
    ///
    /// # Semantics
    ///
    /// Shares the same prefix semantics as [`Operator::list`]: the parent directory is not required to exist; the entry for `path` is yielded if present; missing parents with deeper objects are accepted.
    ///
    /// # Options
    ///
    /// Takes the same [`options::ListOptions`] as [`list_with`](Operator::list_with): traversal (`recursive`), pagination (`limit`, `start_after`), and versioning (`versions`, `deleted`).
    ///
    /// # Examples
    ///
    /// ```
    /// # use anyhow::Result;
    /// # use futures::io;
    /// use futures::TryStreamExt;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut ds = op.lister("path/to/dir/").await?;
    /// while let Some(mut de) = ds.try_next().await? {
    ///     match de.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file")
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir like start a new list via meta.path()")
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn lister(&self, path: &str) -> Result<Lister> {
        self.lister_with(path).await
    }

    /// Create a new lister to list entries that start with the given prefix `path` using additional options.
    ///
    /// # Options
    ///
    /// Same as [`lister_with`](Operator::lister_with); see [`options::ListOptions`] for traversal, pagination, and versioning knobs.
    ///
    /// # Examples
    ///
    /// ## List all files recursively
    ///
    /// ```
    /// # use anyhow::Result;
    /// use futures::TryStreamExt;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut lister = op.lister_with("path/to/dir/").recursive(true).await?;
    /// while let Some(mut entry) = lister.try_next().await? {
    ///     match entry.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file {}", entry.path())
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir {}", entry.path())
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn lister_with(&self, path: &str) -> FutureLister<impl Future<Output = Result<Lister>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            options::ListOptions::default(),
            Self::lister_inner,
        )
    }

    /// Create a new lister to list entries that start with the given prefix `path` using additional options.
    ///
    /// # Semantics
    ///
    /// Inherits the prefix behavior of [`Operator::lister_with`].
    ///
    /// # Options
    ///
    /// Uses [`options::ListOptions`] to control traversal, pagination, and versioning.
    ///
    /// # Examples
    ///
    /// ## List all files recursively
    ///
    /// ```
    /// # use anyhow::Result;
    /// use futures::TryStreamExt;
    /// use opendal_core::options;
    /// use opendal_core::EntryMode;
    /// use opendal_core::Operator;
    /// # async fn test(op: Operator) -> Result<()> {
    /// let mut lister = op
    ///     .lister_options("path/to/dir/", options::ListOptions {
    ///         recursive: true,
    ///         ..Default::default()
    ///     })
    ///     .await?;
    /// while let Some(mut entry) = lister.try_next().await? {
    ///     match entry.metadata().mode() {
    ///         EntryMode::FILE => {
    ///             println!("Handling file {}", entry.path())
    ///         }
    ///         EntryMode::DIR => {
    ///             println!("Handling dir {}", entry.path())
    ///         }
    ///         EntryMode::Unknown => continue,
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub async fn lister_options(&self, path: &str, opts: options::ListOptions) -> Result<Lister> {
        let path = normalize_path(path);
        Self::lister_inner(self.inner().clone(), path, opts).await
    }

    #[inline]
    async fn lister_inner(
        acc: Accessor,
        path: String,
        opts: options::ListOptions,
    ) -> Result<Lister> {
        let args = opts.into();
        let lister = Lister::create(acc, &path, args).await?;
        Ok(lister)
    }
}

/// Operator presign API.
impl Operator {
    /// Presign an operation for stat(head).
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use futures::io;
    /// use opendal_core::Operator;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_stat("test",Duration::from_secs(3600)).await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    /// #    Ok(())
    /// # }
    /// ```
    pub async fn presign_stat(&self, path: &str, expire: Duration) -> Result<PresignedRequest> {
        let path = normalize_path(path);

        let op = OpPresign::new(OpStat::new(), expire);

        let rp = self.inner().presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }

    /// Presign an operation for stat(head).
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use futures::io;
    /// use opendal_core::Operator;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_stat_with("test",Duration::from_secs(3600)).override_content_disposition("attachment; filename=\"othertext.txt\"").await?;
    /// #    Ok(())
    /// # }
    /// ```
    pub fn presign_stat_with(
        &self,
        path: &str,
        expire: Duration,
    ) -> FuturePresignStat<impl Future<Output = Result<PresignedRequest>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            (options::StatOptions::default(), expire),
            Self::presign_stat_inner,
        )
    }

    /// Presign an operation for stat(head) with additional options.
    ///
    /// # Options
    ///
    /// Visit [`options::StatOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    /// use opendal_core::options;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_stat_options(
    ///         "test",
    ///         Duration::from_secs(3600),
    ///         options::StatOptions {
    ///             if_match: Some("<etag>".to_string()),
    ///             ..Default::default()
    ///         }
    ///     ).await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    /// #    Ok(())
    /// # }
    /// ```
    pub async fn presign_stat_options(
        &self,
        path: &str,
        expire: Duration,
        opts: options::StatOptions,
    ) -> Result<PresignedRequest> {
        let path = normalize_path(path);
        Self::presign_stat_inner(self.inner().clone(), path, (opts, expire)).await
    }

    #[inline]
    async fn presign_stat_inner(
        acc: Accessor,
        path: String,
        (opts, expire): (options::StatOptions, Duration),
    ) -> Result<PresignedRequest> {
        let op = OpPresign::new(OpStat::from(opts), expire);
        let rp = acc.presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }

    /// Presign an operation for read.
    ///
    /// # Notes
    ///
    /// ## Extra Options
    ///
    /// `presign_read` is a wrapper of [`Self::presign_read_with`] without any options. To use
    /// extra options like `override_content_disposition`, please use [`Self::presign_read_with`] or
    /// [`Self::presign_read_options] instead.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use futures::io;
    /// use opendal_core::Operator;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_read("test.txt", Duration::from_secs(3600)).await?;
    /// #    Ok(())
    /// # }
    /// ```
    ///
    /// - `signed_req.method()`: `GET`
    /// - `signed_req.uri()`: `https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>`
    /// - `signed_req.headers()`: `{ "host": "s3.amazonaws.com" }`
    ///
    /// We can download this file via `curl` or other tools without credentials:
    ///
    /// ```shell
    /// curl "https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>" -O /tmp/test.txt
    /// ```
    pub async fn presign_read(&self, path: &str, expire: Duration) -> Result<PresignedRequest> {
        let path = normalize_path(path);

        let op = OpPresign::new(OpRead::new(), expire);

        let rp = self.inner().presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }

    /// Presign an operation for read with extra options.
    ///
    /// # Options
    ///
    /// Visit [`options::ReadOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use std::time::Duration;
    ///
    /// use anyhow::Result;
    /// use futures::io;
    /// use opendal_core::Operator;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op
    ///         .presign_read_with("test.txt", Duration::from_secs(3600))
    ///         .override_content_type("text/plain")
    ///         .await?;
    ///     Ok(())
    /// }
    /// ```
    pub fn presign_read_with(
        &self,
        path: &str,
        expire: Duration,
    ) -> FuturePresignRead<impl Future<Output = Result<PresignedRequest>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            (options::ReadOptions::default(), expire),
            Self::presign_read_inner,
        )
    }

    /// Presign an operation for read with additional options.
    ///
    /// # Options
    ///
    /// Visit [`options::ReadOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    /// use opendal_core::options;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_read_options(
    ///         "file",
    ///         Duration::from_secs(3600),
    ///         options::ReadOptions {
    ///             override_content_disposition: Some("attachment; filename=\"othertext.txt\"".to_string()),
    ///             ..Default::default()
    ///         }
    ///     ).await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    /// #    Ok(())
    /// # }
    /// ```
    pub async fn presign_read_options(
        &self,
        path: &str,
        expire: Duration,
        opts: options::ReadOptions,
    ) -> Result<PresignedRequest> {
        let path = normalize_path(path);
        Self::presign_read_inner(self.inner().clone(), path, (opts, expire)).await
    }

    #[inline]
    async fn presign_read_inner(
        acc: Accessor,
        path: String,
        (opts, expire): (options::ReadOptions, Duration),
    ) -> Result<PresignedRequest> {
        let (op_read, _) = opts.into();
        let op = OpPresign::new(op_read, expire);
        let rp = acc.presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }

    /// Presign an operation for write.
    ///
    /// # Notes
    ///
    /// ## Extra Options
    ///
    /// `presign_write` is a wrapper of [`Self::presign_write_with`] without any options. To use
    /// extra options like `content_type`, please use [`Self::presign_write_with`] or
    /// [`Self::presign_write_options`] instead.
    ///
    /// # Example
    ///
    /// ```
    /// use std::time::Duration;
    ///
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op
    ///         .presign_write("test.txt", Duration::from_secs(3600))
    ///         .await?;
    ///     Ok(())
    /// }
    /// ```
    ///
    /// - `signed_req.method()`: `PUT`
    /// - `signed_req.uri()`: `https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>`
    /// - `signed_req.headers()`: `{ "host": "s3.amazonaws.com" }`
    ///
    /// We can upload file as this file via `curl` or other tools without credential:
    ///
    /// ```shell
    /// curl -X PUT "https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>" -d "Hello, World!"
    /// ```
    pub async fn presign_write(&self, path: &str, expire: Duration) -> Result<PresignedRequest> {
        self.presign_write_with(path, expire).await
    }

    /// Presign an operation for write with extra options.
    ///
    /// # Options
    ///
    /// Visit [`options::WriteOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use std::time::Duration;
    ///
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op
    ///         .presign_write_with("test", Duration::from_secs(3600))
    ///         .cache_control("no-store")
    ///         .await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn presign_write_with(
        &self,
        path: &str,
        expire: Duration,
    ) -> FuturePresignWrite<impl Future<Output = Result<PresignedRequest>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            (options::WriteOptions::default(), expire),
            Self::presign_write_inner,
        )
    }

    /// Presign an operation for write with additional options.
    ///
    /// # Options
    ///
    /// Check [`options::WriteOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    /// use opendal_core::options;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_write_options(
    ///         "file",
    ///         Duration::from_secs(3600),
    ///         options::WriteOptions {
    ///             content_type: Some("application/json".to_string()),
    ///             cache_control: Some("max-age=3600".to_string()),
    ///             if_not_exists: true,
    ///             ..Default::default()
    ///         }
    ///     ).await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    /// #    Ok(())
    /// # }
    /// ```
    pub async fn presign_write_options(
        &self,
        path: &str,
        expire: Duration,
        opts: options::WriteOptions,
    ) -> Result<PresignedRequest> {
        let path = normalize_path(path);
        Self::presign_write_inner(self.inner().clone(), path, (opts, expire)).await
    }

    #[inline]
    async fn presign_write_inner(
        acc: Accessor,
        path: String,
        (opts, expire): (options::WriteOptions, Duration),
    ) -> Result<PresignedRequest> {
        let (op_write, _) = opts.into();
        let op = OpPresign::new(op_write, expire);
        let rp = acc.presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }

    /// Presign an operation for delete.
    ///
    /// # Notes
    ///
    /// ## Extra Options
    ///
    /// `presign_delete` is a wrapper of [`Self::presign_delete_with`] without any options.
    ///
    /// # Example
    ///
    /// ```
    /// use std::time::Duration;
    ///
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op
    ///         .presign_delete("test.txt", Duration::from_secs(3600))
    ///         .await?;
    ///     Ok(())
    /// }
    /// ```
    ///
    /// - `signed_req.method()`: `DELETE`
    /// - `signed_req.uri()`: `https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>`
    /// - `signed_req.headers()`: `{ "host": "s3.amazonaws.com" }`
    ///
    /// We can delete file as this file via `curl` or other tools without credential:
    ///
    /// ```shell
    /// curl -X DELETE "https://s3.amazonaws.com/examplebucket/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=access_key_id/20130721/us-east-1/s3/aws4_request&X-Amz-Date=20130721T201207Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=<signature-value>"
    /// ```
    pub async fn presign_delete(&self, path: &str, expire: Duration) -> Result<PresignedRequest> {
        self.presign_delete_with(path, expire).await
    }

    /// Presign an operation for delete without extra options.
    pub fn presign_delete_with(
        &self,
        path: &str,
        expire: Duration,
    ) -> FuturePresignDelete<impl Future<Output = Result<PresignedRequest>>> {
        let path = normalize_path(path);

        OperatorFuture::new(
            self.inner().clone(),
            path,
            (options::DeleteOptions::default(), expire),
            Self::presign_delete_inner,
        )
    }

    /// Presign an operation for delete with additional options.
    ///
    /// # Options
    ///
    /// Visit [`options::DeleteOptions`] for all available options.
    ///
    /// # Example
    ///
    /// ```
    /// use anyhow::Result;
    /// use opendal_core::Operator;
    /// use opendal_core::options;
    /// use std::time::Duration;
    ///
    /// async fn test(op: Operator) -> Result<()> {
    ///     let signed_req = op.presign_delete_options(
    ///         "path/to/file",
    ///         Duration::from_secs(3600),
    ///         options::DeleteOptions {
    ///             ..Default::default()
    ///         }
    ///     ).await?;
    ///     let req = http::Request::builder()
    ///         .method(signed_req.method())
    ///         .uri(signed_req.uri())
    ///         .body(())?;
    ///
    /// #    Ok(())
    /// # }
    /// ```
    pub async fn presign_delete_options(
        &self,
        path: &str,
        expire: Duration,
        opts: options::DeleteOptions,
    ) -> Result<PresignedRequest> {
        let path = normalize_path(path);
        Self::presign_delete_inner(self.inner().clone(), path, (opts, expire)).await
    }

    #[inline]
    async fn presign_delete_inner(
        acc: Accessor,
        path: String,
        (opts, expire): (options::DeleteOptions, Duration),
    ) -> Result<PresignedRequest> {
        let op = OpPresign::new(OpDelete::from(opts), expire);
        let rp = acc.presign(&path, op).await?;
        Ok(rp.into_presigned_request())
    }
}

```
Page 52/55FirstPrevNextLast