opendal 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +24 -24
- data/Cargo.toml +1 -1
- data/DEPENDENCIES.rust.tsv +24 -24
- data/core/CHANGELOG.md +9 -1
- data/core/Cargo.lock +110 -110
- data/core/Cargo.toml +94 -94
- data/core/DEPENDENCIES.rust.tsv +12 -12
- data/core/benches/types/buffer.rs +61 -0
- data/core/benches/vs_fs/Cargo.toml +1 -1
- data/core/benches/vs_s3/Cargo.toml +1 -1
- data/core/core/CHANGELOG.md +9 -1
- data/core/core/src/raw/futures_util.rs +5 -0
- data/core/core/src/raw/oio/copy/block_copy.rs +1 -1
- data/core/core/src/raw/oio/copy/multipart_copy.rs +1 -1
- data/core/core/src/raw/oio/write/block_write.rs +1 -1
- data/core/core/src/raw/oio/write/multipart_write.rs +1 -1
- data/core/core/src/raw/oio/write/position_write.rs +41 -1
- data/core/core/src/types/buffer.rs +131 -0
- data/core/core/src/types/delete/deleter.rs +13 -0
- data/core/core/src/types/mod.rs +1 -0
- data/core/http-transports/reqwest/Cargo.toml +1 -1
- data/core/layers/async-backtrace/Cargo.toml +2 -2
- data/core/layers/await-tree/Cargo.toml +2 -2
- data/core/layers/capability-check/Cargo.toml +2 -2
- data/core/layers/chaos/Cargo.toml +2 -2
- data/core/layers/concurrent-limit/Cargo.toml +2 -2
- data/core/layers/dtrace/Cargo.toml +2 -2
- data/core/layers/fastmetrics/Cargo.toml +3 -3
- data/core/layers/fastrace/Cargo.toml +2 -2
- data/core/layers/foyer/Cargo.toml +2 -2
- data/core/layers/hotpath/Cargo.toml +2 -2
- data/core/layers/immutable-index/Cargo.toml +2 -2
- data/core/layers/logging/Cargo.toml +2 -2
- data/core/layers/metrics/Cargo.toml +3 -3
- data/core/layers/mime-guess/Cargo.toml +2 -2
- data/core/layers/observe-metrics-common/Cargo.toml +1 -1
- data/core/layers/otelmetrics/Cargo.toml +3 -3
- data/core/layers/oteltrace/Cargo.toml +2 -2
- data/core/layers/prometheus/Cargo.toml +3 -3
- data/core/layers/prometheus-client/Cargo.toml +3 -3
- data/core/layers/retry/Cargo.toml +4 -4
- data/core/layers/route/Cargo.toml +3 -3
- data/core/layers/tail-cut/Cargo.toml +2 -2
- data/core/layers/throttle/Cargo.toml +2 -2
- data/core/layers/timeout/Cargo.toml +3 -3
- data/core/layers/tracing/Cargo.toml +2 -2
- data/core/services/aliyun-drive/Cargo.toml +1 -1
- data/core/services/alluxio/Cargo.toml +1 -1
- data/core/services/azblob/Cargo.toml +2 -2
- data/core/services/azdls/Cargo.toml +2 -2
- data/core/services/azfile/Cargo.toml +2 -2
- data/core/services/azure-common/Cargo.toml +1 -1
- data/core/services/b2/Cargo.toml +1 -1
- data/core/services/cacache/Cargo.toml +1 -1
- data/core/services/cloudflare-kv/Cargo.toml +1 -1
- data/core/services/compfs/Cargo.toml +1 -1
- data/core/services/cos/Cargo.toml +1 -1
- data/core/services/d1/Cargo.toml +1 -1
- data/core/services/dashmap/Cargo.toml +1 -1
- data/core/services/dbfs/Cargo.toml +1 -1
- data/core/services/dropbox/Cargo.toml +1 -1
- data/core/services/etcd/Cargo.toml +1 -1
- data/core/services/foundationdb/Cargo.toml +1 -1
- data/core/services/foyer/Cargo.toml +3 -3
- data/core/services/fs/Cargo.toml +1 -1
- data/core/services/ftp/Cargo.toml +1 -1
- data/core/services/gcs/Cargo.toml +1 -1
- data/core/services/gcs-grpc/Cargo.toml +1 -1
- data/core/services/gdrive/Cargo.toml +1 -1
- data/core/services/ghac/Cargo.toml +2 -2
- data/core/services/github/Cargo.toml +1 -1
- data/core/services/goosefs/Cargo.toml +2 -2
- data/core/services/goosefs/src/backend.rs +43 -16
- data/core/services/goosefs/src/config.rs +4 -1
- data/core/services/goosefs/src/docs.md +1 -1
- data/core/services/gridfs/Cargo.toml +1 -1
- data/core/services/hdfs/Cargo.toml +2 -2
- data/core/services/hdfs/src/backend.rs +15 -7
- data/core/services/hdfs/src/core.rs +55 -16
- data/core/services/hdfs/src/docs.md +9 -1
- data/core/services/hdfs-native/Cargo.toml +1 -1
- data/core/services/hf/Cargo.toml +5 -2
- data/core/services/hf/src/backend.rs +8 -3
- data/core/services/hf/src/config.rs +4 -2
- data/core/services/hf/src/docs.md +6 -2
- data/core/services/hf/src/reader.rs +163 -68
- data/core/services/http/Cargo.toml +3 -3
- data/core/services/ipfs/Cargo.toml +1 -1
- data/core/services/ipmfs/Cargo.toml +1 -1
- data/core/services/koofr/Cargo.toml +1 -1
- data/core/services/lakefs/Cargo.toml +1 -1
- data/core/services/memcached/Cargo.toml +1 -1
- data/core/services/mini_moka/Cargo.toml +1 -1
- data/core/services/moka/Cargo.toml +1 -1
- data/core/services/mongodb/Cargo.toml +1 -1
- data/core/services/monoiofs/Cargo.toml +1 -1
- data/core/services/mysql/Cargo.toml +1 -1
- data/core/services/obs/Cargo.toml +1 -1
- data/core/services/onedrive/Cargo.toml +1 -1
- data/core/services/opfs/Cargo.toml +1 -1
- data/core/services/oss/Cargo.toml +1 -1
- data/core/services/oss/src/backend.rs +143 -2
- data/core/services/oss/src/docs.md +12 -0
- data/core/services/pcloud/Cargo.toml +1 -1
- data/core/services/persy/Cargo.toml +1 -1
- data/core/services/postgresql/Cargo.toml +1 -1
- data/core/services/redb/Cargo.toml +1 -1
- data/core/services/redis/Cargo.toml +1 -1
- data/core/services/rocksdb/Cargo.toml +1 -1
- data/core/services/s3/Cargo.toml +1 -1
- data/core/services/seafile/Cargo.toml +1 -1
- data/core/services/sftp/Cargo.toml +1 -1
- data/core/services/sled/Cargo.toml +1 -1
- data/core/services/sqlite/Cargo.toml +1 -1
- data/core/services/surrealdb/Cargo.toml +1 -1
- data/core/services/swift/Cargo.toml +1 -1
- data/core/services/tikv/Cargo.toml +1 -1
- data/core/services/tos/Cargo.toml +1 -1
- data/core/services/upyun/Cargo.toml +1 -1
- data/core/services/vercel-artifacts/Cargo.toml +1 -1
- data/core/services/vercel-blob/Cargo.toml +1 -1
- data/core/services/webdav/Cargo.toml +1 -1
- data/core/services/webdav/src/backend.rs +10 -21
- data/core/services/webdav/src/config.rs +5 -14
- data/core/services/webhdfs/Cargo.toml +1 -1
- data/core/services/yandex-disk/Cargo.toml +1 -1
- data/core/testkit/Cargo.toml +4 -4
- metadata +2 -2
data/core/Cargo.toml
CHANGED
|
@@ -39,7 +39,7 @@ homepage = "https://opendal.apache.org/"
|
|
|
39
39
|
license = "Apache-2.0"
|
|
40
40
|
repository = "https://github.com/apache/opendal"
|
|
41
41
|
rust-version = "1.91"
|
|
42
|
-
version = "0.59.
|
|
42
|
+
version = "0.59.4"
|
|
43
43
|
|
|
44
44
|
[workspace.dependencies]
|
|
45
45
|
asyncband = { version = "0.7.1" }
|
|
@@ -246,103 +246,103 @@ required-features = ["tests"]
|
|
|
246
246
|
|
|
247
247
|
[dependencies]
|
|
248
248
|
ctor = { workspace = true, optional = true }
|
|
249
|
-
opendal-core = { path = "core", version = "0.59.
|
|
250
|
-
opendal-http-transport-reqwest = { path = "http-transports/reqwest", version = "0.59.
|
|
251
|
-
opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = "0.59.
|
|
252
|
-
opendal-layer-await-tree = { path = "layers/await-tree", version = "0.59.
|
|
253
|
-
opendal-layer-capability-check = { path = "layers/capability-check", version = "0.59.
|
|
254
|
-
opendal-layer-chaos = { path = "layers/chaos", version = "0.59.
|
|
255
|
-
opendal-layer-concurrent-limit = { path = "layers/concurrent-limit", version = "0.59.
|
|
256
|
-
opendal-layer-fastmetrics = { path = "layers/fastmetrics", version = "0.59.
|
|
257
|
-
opendal-layer-fastrace = { path = "layers/fastrace", version = "0.59.
|
|
258
|
-
opendal-layer-foyer = { path = "layers/foyer", version = "0.59.
|
|
259
|
-
opendal-layer-hotpath = { path = "layers/hotpath", version = "0.59.
|
|
260
|
-
opendal-layer-immutable-index = { path = "layers/immutable-index", version = "0.59.
|
|
261
|
-
opendal-layer-logging = { path = "layers/logging", version = "0.59.
|
|
262
|
-
opendal-layer-metrics = { path = "layers/metrics", version = "0.59.
|
|
263
|
-
opendal-layer-mime-guess = { path = "layers/mime-guess", version = "0.59.
|
|
264
|
-
opendal-layer-observe-metrics-common = { path = "layers/observe-metrics-common", version = "0.59.
|
|
265
|
-
opendal-layer-otelmetrics = { path = "layers/otelmetrics", version = "0.59.
|
|
266
|
-
opendal-layer-oteltrace = { path = "layers/oteltrace", version = "0.59.
|
|
267
|
-
opendal-layer-prometheus = { path = "layers/prometheus", version = "0.59.
|
|
268
|
-
opendal-layer-prometheus-client = { path = "layers/prometheus-client", version = "0.59.
|
|
269
|
-
opendal-layer-retry = { path = "layers/retry", version = "0.59.
|
|
270
|
-
opendal-layer-route = { path = "layers/route", version = "0.59.
|
|
271
|
-
opendal-layer-tail-cut = { path = "layers/tail-cut", version = "0.59.
|
|
272
|
-
opendal-layer-throttle = { path = "layers/throttle", version = "0.59.
|
|
273
|
-
opendal-layer-timeout = { path = "layers/timeout", version = "0.59.
|
|
274
|
-
opendal-layer-tracing = { path = "layers/tracing", version = "0.59.
|
|
275
|
-
opendal-service-aliyun-drive = { path = "services/aliyun-drive", version = "0.59.
|
|
276
|
-
opendal-service-alluxio = { path = "services/alluxio", version = "0.59.
|
|
277
|
-
opendal-service-azblob = { path = "services/azblob", version = "0.59.
|
|
278
|
-
opendal-service-azdls = { path = "services/azdls", version = "0.59.
|
|
279
|
-
opendal-service-azfile = { path = "services/azfile", version = "0.59.
|
|
280
|
-
opendal-service-b2 = { path = "services/b2", version = "0.59.
|
|
281
|
-
opendal-service-cacache = { path = "services/cacache", version = "0.59.
|
|
282
|
-
opendal-service-cloudflare-kv = { path = "services/cloudflare-kv", version = "0.59.
|
|
283
|
-
opendal-service-compfs = { path = "services/compfs", version = "0.59.
|
|
284
|
-
opendal-service-cos = { path = "services/cos", version = "0.59.
|
|
285
|
-
opendal-service-d1 = { path = "services/d1", version = "0.59.
|
|
286
|
-
opendal-service-dashmap = { path = "services/dashmap", version = "0.59.
|
|
287
|
-
opendal-service-dbfs = { path = "services/dbfs", version = "0.59.
|
|
288
|
-
opendal-service-dropbox = { path = "services/dropbox", version = "0.59.
|
|
289
|
-
opendal-service-etcd = { path = "services/etcd", version = "0.59.
|
|
290
|
-
opendal-service-foundationdb = { path = "services/foundationdb", version = "0.59.
|
|
291
|
-
opendal-service-foyer = { path = "services/foyer", version = "0.59.
|
|
292
|
-
opendal-service-fs = { path = "services/fs", version = "0.59.
|
|
293
|
-
opendal-service-ftp = { path = "services/ftp", version = "0.59.
|
|
294
|
-
opendal-service-gcs = { path = "services/gcs", version = "0.59.
|
|
295
|
-
opendal-service-gcs-grpc = { path = "services/gcs-grpc", version = "0.59.
|
|
296
|
-
opendal-service-gdrive = { path = "services/gdrive", version = "0.59.
|
|
297
|
-
opendal-service-ghac = { path = "services/ghac", version = "0.59.
|
|
298
|
-
opendal-service-github = { path = "services/github", version = "0.59.
|
|
299
|
-
opendal-service-goosefs = { path = "services/goosefs", version = "0.59.
|
|
300
|
-
opendal-service-gridfs = { path = "services/gridfs", version = "0.59.
|
|
301
|
-
opendal-service-hdfs = { path = "services/hdfs", version = "0.59.
|
|
302
|
-
opendal-service-hdfs-native = { path = "services/hdfs-native", version = "0.59.
|
|
303
|
-
opendal-service-hf = { path = "services/hf", version = "0.59.
|
|
304
|
-
opendal-service-http = { path = "services/http", version = "0.59.
|
|
305
|
-
opendal-service-ipfs = { path = "services/ipfs", version = "0.59.
|
|
306
|
-
opendal-service-ipmfs = { path = "services/ipmfs", version = "0.59.
|
|
307
|
-
opendal-service-koofr = { path = "services/koofr", version = "0.59.
|
|
308
|
-
opendal-service-lakefs = { path = "services/lakefs", version = "0.59.
|
|
309
|
-
opendal-service-memcached = { path = "services/memcached", version = "0.59.
|
|
310
|
-
opendal-service-mini-moka = { path = "services/mini_moka", version = "0.59.
|
|
311
|
-
opendal-service-moka = { path = "services/moka", version = "0.59.
|
|
312
|
-
opendal-service-mongodb = { path = "services/mongodb", version = "0.59.
|
|
313
|
-
opendal-service-monoiofs = { path = "services/monoiofs", version = "0.59.
|
|
314
|
-
opendal-service-mysql = { path = "services/mysql", version = "0.59.
|
|
315
|
-
opendal-service-obs = { path = "services/obs", version = "0.59.
|
|
316
|
-
opendal-service-onedrive = { path = "services/onedrive", version = "0.59.
|
|
317
|
-
opendal-service-oss = { path = "services/oss", version = "0.59.
|
|
318
|
-
opendal-service-pcloud = { path = "services/pcloud", version = "0.59.
|
|
319
|
-
opendal-service-persy = { path = "services/persy", version = "0.59.
|
|
320
|
-
opendal-service-postgresql = { path = "services/postgresql", version = "0.59.
|
|
321
|
-
opendal-service-redb = { path = "services/redb", version = "0.59.
|
|
322
|
-
opendal-service-redis = { path = "services/redis", version = "0.59.
|
|
323
|
-
opendal-service-rocksdb = { path = "services/rocksdb", version = "0.59.
|
|
324
|
-
opendal-service-s3 = { path = "services/s3", version = "0.59.
|
|
325
|
-
opendal-service-seafile = { path = "services/seafile", version = "0.59.
|
|
326
|
-
opendal-service-sftp = { path = "services/sftp", version = "0.59.
|
|
327
|
-
opendal-service-sled = { path = "services/sled", version = "0.59.
|
|
328
|
-
opendal-service-sqlite = { path = "services/sqlite", version = "0.59.
|
|
329
|
-
opendal-service-surrealdb = { path = "services/surrealdb", version = "0.59.
|
|
330
|
-
opendal-service-swift = { path = "services/swift", version = "0.59.
|
|
331
|
-
opendal-service-tikv = { path = "services/tikv", version = "0.59.
|
|
332
|
-
opendal-service-tos = { path = "services/tos", version = "0.59.
|
|
333
|
-
opendal-service-upyun = { path = "services/upyun", version = "0.59.
|
|
334
|
-
opendal-service-vercel-artifacts = { path = "services/vercel-artifacts", version = "0.59.
|
|
335
|
-
opendal-service-vercel-blob = { path = "services/vercel-blob", version = "0.59.
|
|
336
|
-
opendal-service-webdav = { path = "services/webdav", version = "0.59.
|
|
337
|
-
opendal-service-webhdfs = { path = "services/webhdfs", version = "0.59.
|
|
338
|
-
opendal-service-yandex-disk = { path = "services/yandex-disk", version = "0.59.
|
|
339
|
-
opendal-testkit = { path = "testkit", version = "0.59.
|
|
249
|
+
opendal-core = { path = "core", version = "0.59.4", default-features = false }
|
|
250
|
+
opendal-http-transport-reqwest = { path = "http-transports/reqwest", version = "0.59.4", optional = true, default-features = false }
|
|
251
|
+
opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = "0.59.4", optional = true, default-features = false }
|
|
252
|
+
opendal-layer-await-tree = { path = "layers/await-tree", version = "0.59.4", optional = true, default-features = false }
|
|
253
|
+
opendal-layer-capability-check = { path = "layers/capability-check", version = "0.59.4", optional = true, default-features = false }
|
|
254
|
+
opendal-layer-chaos = { path = "layers/chaos", version = "0.59.4", optional = true, default-features = false }
|
|
255
|
+
opendal-layer-concurrent-limit = { path = "layers/concurrent-limit", version = "0.59.4", optional = true, default-features = false }
|
|
256
|
+
opendal-layer-fastmetrics = { path = "layers/fastmetrics", version = "0.59.4", optional = true, default-features = false }
|
|
257
|
+
opendal-layer-fastrace = { path = "layers/fastrace", version = "0.59.4", optional = true, default-features = false }
|
|
258
|
+
opendal-layer-foyer = { path = "layers/foyer", version = "0.59.4", optional = true, default-features = false }
|
|
259
|
+
opendal-layer-hotpath = { path = "layers/hotpath", version = "0.59.4", optional = true, default-features = false }
|
|
260
|
+
opendal-layer-immutable-index = { path = "layers/immutable-index", version = "0.59.4", optional = true, default-features = false }
|
|
261
|
+
opendal-layer-logging = { path = "layers/logging", version = "0.59.4", optional = true, default-features = false }
|
|
262
|
+
opendal-layer-metrics = { path = "layers/metrics", version = "0.59.4", optional = true, default-features = false }
|
|
263
|
+
opendal-layer-mime-guess = { path = "layers/mime-guess", version = "0.59.4", optional = true, default-features = false }
|
|
264
|
+
opendal-layer-observe-metrics-common = { path = "layers/observe-metrics-common", version = "0.59.4", optional = true, default-features = false }
|
|
265
|
+
opendal-layer-otelmetrics = { path = "layers/otelmetrics", version = "0.59.4", optional = true, default-features = false }
|
|
266
|
+
opendal-layer-oteltrace = { path = "layers/oteltrace", version = "0.59.4", optional = true, default-features = false }
|
|
267
|
+
opendal-layer-prometheus = { path = "layers/prometheus", version = "0.59.4", optional = true, default-features = false }
|
|
268
|
+
opendal-layer-prometheus-client = { path = "layers/prometheus-client", version = "0.59.4", optional = true, default-features = false }
|
|
269
|
+
opendal-layer-retry = { path = "layers/retry", version = "0.59.4", optional = true, default-features = false }
|
|
270
|
+
opendal-layer-route = { path = "layers/route", version = "0.59.4", optional = true, default-features = false }
|
|
271
|
+
opendal-layer-tail-cut = { path = "layers/tail-cut", version = "0.59.4", optional = true, default-features = false }
|
|
272
|
+
opendal-layer-throttle = { path = "layers/throttle", version = "0.59.4", optional = true, default-features = false }
|
|
273
|
+
opendal-layer-timeout = { path = "layers/timeout", version = "0.59.4", optional = true, default-features = false }
|
|
274
|
+
opendal-layer-tracing = { path = "layers/tracing", version = "0.59.4", optional = true, default-features = false }
|
|
275
|
+
opendal-service-aliyun-drive = { path = "services/aliyun-drive", version = "0.59.4", optional = true, default-features = false }
|
|
276
|
+
opendal-service-alluxio = { path = "services/alluxio", version = "0.59.4", optional = true, default-features = false }
|
|
277
|
+
opendal-service-azblob = { path = "services/azblob", version = "0.59.4", optional = true, default-features = false }
|
|
278
|
+
opendal-service-azdls = { path = "services/azdls", version = "0.59.4", optional = true, default-features = false }
|
|
279
|
+
opendal-service-azfile = { path = "services/azfile", version = "0.59.4", optional = true, default-features = false }
|
|
280
|
+
opendal-service-b2 = { path = "services/b2", version = "0.59.4", optional = true, default-features = false }
|
|
281
|
+
opendal-service-cacache = { path = "services/cacache", version = "0.59.4", optional = true, default-features = false }
|
|
282
|
+
opendal-service-cloudflare-kv = { path = "services/cloudflare-kv", version = "0.59.4", optional = true, default-features = false }
|
|
283
|
+
opendal-service-compfs = { path = "services/compfs", version = "0.59.4", optional = true, default-features = false }
|
|
284
|
+
opendal-service-cos = { path = "services/cos", version = "0.59.4", optional = true, default-features = false }
|
|
285
|
+
opendal-service-d1 = { path = "services/d1", version = "0.59.4", optional = true, default-features = false }
|
|
286
|
+
opendal-service-dashmap = { path = "services/dashmap", version = "0.59.4", optional = true, default-features = false }
|
|
287
|
+
opendal-service-dbfs = { path = "services/dbfs", version = "0.59.4", optional = true, default-features = false }
|
|
288
|
+
opendal-service-dropbox = { path = "services/dropbox", version = "0.59.4", optional = true, default-features = false }
|
|
289
|
+
opendal-service-etcd = { path = "services/etcd", version = "0.59.4", optional = true, default-features = false }
|
|
290
|
+
opendal-service-foundationdb = { path = "services/foundationdb", version = "0.59.4", optional = true, default-features = false }
|
|
291
|
+
opendal-service-foyer = { path = "services/foyer", version = "0.59.4", optional = true, default-features = false }
|
|
292
|
+
opendal-service-fs = { path = "services/fs", version = "0.59.4", optional = true, default-features = false }
|
|
293
|
+
opendal-service-ftp = { path = "services/ftp", version = "0.59.4", optional = true, default-features = false }
|
|
294
|
+
opendal-service-gcs = { path = "services/gcs", version = "0.59.4", optional = true, default-features = false }
|
|
295
|
+
opendal-service-gcs-grpc = { path = "services/gcs-grpc", version = "0.59.4", optional = true, default-features = false }
|
|
296
|
+
opendal-service-gdrive = { path = "services/gdrive", version = "0.59.4", optional = true, default-features = false }
|
|
297
|
+
opendal-service-ghac = { path = "services/ghac", version = "0.59.4", optional = true, default-features = false }
|
|
298
|
+
opendal-service-github = { path = "services/github", version = "0.59.4", optional = true, default-features = false }
|
|
299
|
+
opendal-service-goosefs = { path = "services/goosefs", version = "0.59.4", optional = true, default-features = false }
|
|
300
|
+
opendal-service-gridfs = { path = "services/gridfs", version = "0.59.4", optional = true, default-features = false }
|
|
301
|
+
opendal-service-hdfs = { path = "services/hdfs", version = "0.59.4", optional = true, default-features = false }
|
|
302
|
+
opendal-service-hdfs-native = { path = "services/hdfs-native", version = "0.59.4", optional = true, default-features = false }
|
|
303
|
+
opendal-service-hf = { path = "services/hf", version = "0.59.4", optional = true, default-features = false }
|
|
304
|
+
opendal-service-http = { path = "services/http", version = "0.59.4", optional = true, default-features = false }
|
|
305
|
+
opendal-service-ipfs = { path = "services/ipfs", version = "0.59.4", optional = true, default-features = false }
|
|
306
|
+
opendal-service-ipmfs = { path = "services/ipmfs", version = "0.59.4", optional = true, default-features = false }
|
|
307
|
+
opendal-service-koofr = { path = "services/koofr", version = "0.59.4", optional = true, default-features = false }
|
|
308
|
+
opendal-service-lakefs = { path = "services/lakefs", version = "0.59.4", optional = true, default-features = false }
|
|
309
|
+
opendal-service-memcached = { path = "services/memcached", version = "0.59.4", optional = true, default-features = false }
|
|
310
|
+
opendal-service-mini-moka = { path = "services/mini_moka", version = "0.59.4", optional = true, default-features = false }
|
|
311
|
+
opendal-service-moka = { path = "services/moka", version = "0.59.4", optional = true, default-features = false }
|
|
312
|
+
opendal-service-mongodb = { path = "services/mongodb", version = "0.59.4", optional = true, default-features = false }
|
|
313
|
+
opendal-service-monoiofs = { path = "services/monoiofs", version = "0.59.4", optional = true, default-features = false }
|
|
314
|
+
opendal-service-mysql = { path = "services/mysql", version = "0.59.4", optional = true, default-features = false }
|
|
315
|
+
opendal-service-obs = { path = "services/obs", version = "0.59.4", optional = true, default-features = false }
|
|
316
|
+
opendal-service-onedrive = { path = "services/onedrive", version = "0.59.4", optional = true, default-features = false }
|
|
317
|
+
opendal-service-oss = { path = "services/oss", version = "0.59.4", optional = true, default-features = false }
|
|
318
|
+
opendal-service-pcloud = { path = "services/pcloud", version = "0.59.4", optional = true, default-features = false }
|
|
319
|
+
opendal-service-persy = { path = "services/persy", version = "0.59.4", optional = true, default-features = false }
|
|
320
|
+
opendal-service-postgresql = { path = "services/postgresql", version = "0.59.4", optional = true, default-features = false }
|
|
321
|
+
opendal-service-redb = { path = "services/redb", version = "0.59.4", optional = true, default-features = false }
|
|
322
|
+
opendal-service-redis = { path = "services/redis", version = "0.59.4", optional = true, default-features = false }
|
|
323
|
+
opendal-service-rocksdb = { path = "services/rocksdb", version = "0.59.4", optional = true, default-features = false }
|
|
324
|
+
opendal-service-s3 = { path = "services/s3", version = "0.59.4", optional = true, default-features = false }
|
|
325
|
+
opendal-service-seafile = { path = "services/seafile", version = "0.59.4", optional = true, default-features = false }
|
|
326
|
+
opendal-service-sftp = { path = "services/sftp", version = "0.59.4", optional = true, default-features = false }
|
|
327
|
+
opendal-service-sled = { path = "services/sled", version = "0.59.4", optional = true, default-features = false }
|
|
328
|
+
opendal-service-sqlite = { path = "services/sqlite", version = "0.59.4", optional = true, default-features = false }
|
|
329
|
+
opendal-service-surrealdb = { path = "services/surrealdb", version = "0.59.4", optional = true, default-features = false }
|
|
330
|
+
opendal-service-swift = { path = "services/swift", version = "0.59.4", optional = true, default-features = false }
|
|
331
|
+
opendal-service-tikv = { path = "services/tikv", version = "0.59.4", optional = true, default-features = false }
|
|
332
|
+
opendal-service-tos = { path = "services/tos", version = "0.59.4", optional = true, default-features = false }
|
|
333
|
+
opendal-service-upyun = { path = "services/upyun", version = "0.59.4", optional = true, default-features = false }
|
|
334
|
+
opendal-service-vercel-artifacts = { path = "services/vercel-artifacts", version = "0.59.4", optional = true, default-features = false }
|
|
335
|
+
opendal-service-vercel-blob = { path = "services/vercel-blob", version = "0.59.4", optional = true, default-features = false }
|
|
336
|
+
opendal-service-webdav = { path = "services/webdav", version = "0.59.4", optional = true, default-features = false }
|
|
337
|
+
opendal-service-webhdfs = { path = "services/webhdfs", version = "0.59.4", optional = true, default-features = false }
|
|
338
|
+
opendal-service-yandex-disk = { path = "services/yandex-disk", version = "0.59.4", optional = true, default-features = false }
|
|
339
|
+
opendal-testkit = { path = "testkit", version = "0.59.4", optional = true }
|
|
340
340
|
|
|
341
341
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
342
|
-
opendal-layer-dtrace = { path = "layers/dtrace", version = "0.59.
|
|
342
|
+
opendal-layer-dtrace = { path = "layers/dtrace", version = "0.59.4", optional = true, default-features = false }
|
|
343
343
|
|
|
344
344
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
345
|
-
opendal-service-opfs = { path = "services/opfs", version = "0.59.
|
|
345
|
+
opendal-service-opfs = { path = "services/opfs", version = "0.59.4", optional = true, default-features = false }
|
|
346
346
|
|
|
347
347
|
[dev-dependencies]
|
|
348
348
|
anyhow = "1.0"
|
data/core/DEPENDENCIES.rust.tsv
CHANGED
|
@@ -115,18 +115,18 @@ memchr@2.8.2 X X
|
|
|
115
115
|
mime@0.3.17 X X
|
|
116
116
|
mio@1.2.0 X
|
|
117
117
|
once_cell@1.21.4 X X
|
|
118
|
-
opendal@0.59.
|
|
119
|
-
opendal-core@0.59.
|
|
120
|
-
opendal-http-transport-reqwest@0.59.
|
|
121
|
-
opendal-layer-concurrent-limit@0.59.
|
|
122
|
-
opendal-layer-logging@0.59.
|
|
123
|
-
opendal-layer-retry@0.59.
|
|
124
|
-
opendal-layer-timeout@0.59.
|
|
125
|
-
opendal-service-fs@0.59.
|
|
126
|
-
opendal-service-goosefs@0.59.
|
|
127
|
-
opendal-service-opfs@0.59.
|
|
128
|
-
opendal-service-s3@0.59.
|
|
129
|
-
opendal-testkit@0.59.
|
|
118
|
+
opendal@0.59.4 X
|
|
119
|
+
opendal-core@0.59.4 X
|
|
120
|
+
opendal-http-transport-reqwest@0.59.4 X
|
|
121
|
+
opendal-layer-concurrent-limit@0.59.4 X
|
|
122
|
+
opendal-layer-logging@0.59.4 X
|
|
123
|
+
opendal-layer-retry@0.59.4 X
|
|
124
|
+
opendal-layer-timeout@0.59.4 X
|
|
125
|
+
opendal-service-fs@0.59.4 X
|
|
126
|
+
opendal-service-goosefs@0.59.4 X
|
|
127
|
+
opendal-service-opfs@0.59.4 X
|
|
128
|
+
opendal-service-s3@0.59.4 X
|
|
129
|
+
opendal-testkit@0.59.4 X
|
|
130
130
|
openssl-probe@0.2.1 X X
|
|
131
131
|
ordered-multimap@0.7.3 X
|
|
132
132
|
parking_lot_core@0.9.12 X X
|
|
@@ -20,6 +20,7 @@ use bytes::Bytes;
|
|
|
20
20
|
use divan::Bencher;
|
|
21
21
|
use divan::black_box;
|
|
22
22
|
use opendal::Buffer;
|
|
23
|
+
use opendal::BufferCursor;
|
|
23
24
|
|
|
24
25
|
mod chunk {
|
|
25
26
|
use super::*;
|
|
@@ -108,3 +109,63 @@ mod iterator {
|
|
|
108
109
|
.bench_refs(|buffer| for _ in buffer {});
|
|
109
110
|
}
|
|
110
111
|
}
|
|
112
|
+
|
|
113
|
+
mod cursor {
|
|
114
|
+
use super::*;
|
|
115
|
+
|
|
116
|
+
fn create_large_buffer(size: usize) -> Buffer {
|
|
117
|
+
let mut buf = Vec::with_capacity(size);
|
|
118
|
+
for i in 0..size {
|
|
119
|
+
buf.push(((i * 7) % 256) as u8);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Split into 1MB chunks
|
|
123
|
+
let mut pos = 0;
|
|
124
|
+
let mut chunks = vec![];
|
|
125
|
+
while pos < buf.len() {
|
|
126
|
+
let len = (buf.len() - pos).min(1024 * 1024);
|
|
127
|
+
chunks.push(bytes::Bytes::from(buf[pos..pos + len].to_vec()));
|
|
128
|
+
pos += len;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
Buffer::from(chunks)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#[divan::bench]
|
|
135
|
+
fn buffer_to_vec(bencher: Bencher) {
|
|
136
|
+
use std::io::Read;
|
|
137
|
+
|
|
138
|
+
let src = create_large_buffer(50 * 1024 * 1024); // 50MB
|
|
139
|
+
|
|
140
|
+
bencher.bench(|| {
|
|
141
|
+
let mut cursor = std::io::Cursor::new(black_box(src.to_vec()));
|
|
142
|
+
let mut buf = vec![0u8; 128 * 1024];
|
|
143
|
+
loop {
|
|
144
|
+
let len = cursor.read(&mut buf[..]).unwrap();
|
|
145
|
+
if len == 0 {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
black_box(&buf[..len]);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
#[divan::bench]
|
|
154
|
+
fn buffer_cursor(bencher: Bencher) {
|
|
155
|
+
use std::io::Read;
|
|
156
|
+
|
|
157
|
+
let src = create_large_buffer(50 * 1024 * 1024); // 50MB
|
|
158
|
+
|
|
159
|
+
bencher.bench(|| {
|
|
160
|
+
let mut cursor = BufferCursor::new(black_box(src.clone()));
|
|
161
|
+
let mut buf = vec![0u8; 128 * 1024];
|
|
162
|
+
loop {
|
|
163
|
+
let len = cursor.read(&mut buf[..]).unwrap();
|
|
164
|
+
if len == 0 {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
black_box(&buf[..len]);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
data/core/core/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
# v0.59.4
|
|
2
|
+
|
|
3
|
+
- [Changes since v0.59.3](https://github.com/apache/opendal/compare/v0.59.3...3b559e7527b73be7ea9ea7dbb6c9f2aa14e1c0e7)
|
|
4
|
+
|
|
5
|
+
# v0.59.3
|
|
6
|
+
|
|
7
|
+
- [Release notes](https://github.com/apache/opendal/releases/tag/v0.59.3)
|
|
8
|
+
|
|
1
9
|
# v0.59.2
|
|
2
10
|
|
|
3
|
-
- [
|
|
11
|
+
- [Release notes](https://github.com/apache/opendal/releases/tag/v0.59.2)
|
|
4
12
|
|
|
5
13
|
# Change Log
|
|
6
14
|
|
|
@@ -157,6 +157,11 @@ pub struct ConcurrentTasks<I, O> {
|
|
|
157
157
|
impl<I: Send + 'static, O: Send + 'static> ConcurrentTasks<I, O> {
|
|
158
158
|
/// Create a new concurrent tasks with given executor, concurrent, prefetch and factory.
|
|
159
159
|
///
|
|
160
|
+
/// `prefetch` is extra completed tasks allowed in the queue before
|
|
161
|
+
/// [`Self::execute`] waits to collect the head. Pass `0` when the caller
|
|
162
|
+
/// does not collect results while still submitting work; otherwise failed
|
|
163
|
+
/// tasks keep their inputs until collection.
|
|
164
|
+
///
|
|
160
165
|
/// The factory is a function pointer that shouldn't capture any context.
|
|
161
166
|
pub fn new(
|
|
162
167
|
executor: Executor,
|
|
@@ -133,7 +133,7 @@ impl<C: BlockCopy> BlockCopier<C> {
|
|
|
133
133
|
completed: false,
|
|
134
134
|
metadata: None,
|
|
135
135
|
|
|
136
|
-
tasks: ConcurrentTasks::new(executor, concurrent,
|
|
136
|
+
tasks: ConcurrentTasks::new(executor, concurrent, 0, |input| {
|
|
137
137
|
Box::pin(async move {
|
|
138
138
|
let size = input.range.size().expect("block copy range must be sized");
|
|
139
139
|
let fut = input.copier.copy_block(input.block_id, input.range);
|
|
@@ -159,7 +159,7 @@ impl<C: MultipartCopy> MultipartCopier<C> {
|
|
|
159
159
|
completed: false,
|
|
160
160
|
metadata: None,
|
|
161
161
|
|
|
162
|
-
tasks: ConcurrentTasks::new(executor, concurrent,
|
|
162
|
+
tasks: ConcurrentTasks::new(executor, concurrent, 0, |input| {
|
|
163
163
|
Box::pin(async move {
|
|
164
164
|
let size = input
|
|
165
165
|
.range
|
|
@@ -125,7 +125,7 @@ impl<W: BlockWrite> BlockWriter<W> {
|
|
|
125
125
|
block_ids: Vec::new(),
|
|
126
126
|
cache: None,
|
|
127
127
|
|
|
128
|
-
tasks: ConcurrentTasks::new(executor, concurrent,
|
|
128
|
+
tasks: ConcurrentTasks::new(executor, concurrent, 0, |input| {
|
|
129
129
|
Box::pin(async move {
|
|
130
130
|
let fut = input
|
|
131
131
|
.w
|
|
@@ -186,7 +186,7 @@ impl<W: MultipartWrite> MultipartWriter<W> {
|
|
|
186
186
|
cache: None,
|
|
187
187
|
next_part_number: 0,
|
|
188
188
|
|
|
189
|
-
tasks: ConcurrentTasks::new(executor, concurrent,
|
|
189
|
+
tasks: ConcurrentTasks::new(executor, concurrent, 0, |input| {
|
|
190
190
|
Box::pin({
|
|
191
191
|
async move {
|
|
192
192
|
let fut = async {
|
|
@@ -88,7 +88,7 @@ impl<W: PositionWrite> PositionWriter<W> {
|
|
|
88
88
|
next_offset: 0,
|
|
89
89
|
cache: None,
|
|
90
90
|
|
|
91
|
-
tasks: ConcurrentTasks::new(executor, concurrent,
|
|
91
|
+
tasks: ConcurrentTasks::new(executor, concurrent, 0, |input| {
|
|
92
92
|
Box::pin(async move {
|
|
93
93
|
let fut = input.w.write_all_at(input.offset, input.bytes.clone());
|
|
94
94
|
match input.executor.timeout() {
|
|
@@ -280,4 +280,44 @@ mod tests {
|
|
|
280
280
|
let actual_size = w.w.lock().unwrap().length;
|
|
281
281
|
assert_eq!(actual_size, total_size);
|
|
282
282
|
}
|
|
283
|
+
|
|
284
|
+
struct FailingWrite;
|
|
285
|
+
|
|
286
|
+
impl PositionWrite for FailingWrite {
|
|
287
|
+
async fn write_all_at(&self, _offset: u64, _buf: Buffer) -> Result<()> {
|
|
288
|
+
Err(Error::new(ErrorKind::Unexpected, "backend write failed"))
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async fn close(&self, _size: u64) -> Result<Metadata> {
|
|
292
|
+
Ok(MetadataBuilder::unknown().build())
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async fn abort(&self) -> Result<()> {
|
|
296
|
+
Ok(())
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
#[tokio::test]
|
|
301
|
+
async fn test_position_writer_surfaces_permanent_error_within_concurrent_window() {
|
|
302
|
+
let concurrent = 8;
|
|
303
|
+
let mut w = PositionWriter::new(Executor::default(), FailingWrite, concurrent);
|
|
304
|
+
let bs = Buffer::from(vec![0u8; 8]);
|
|
305
|
+
|
|
306
|
+
let mut first_error_at = None;
|
|
307
|
+
for i in 1..=concurrent + 4 {
|
|
308
|
+
match w.write(bs.clone()).await {
|
|
309
|
+
Ok(()) => continue,
|
|
310
|
+
Err(_) => {
|
|
311
|
+
first_error_at = Some(i);
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
let first_error_at = first_error_at
|
|
318
|
+
.expect("write must surface the backend error inside the concurrent window");
|
|
319
|
+
// One write stays in cache; ConcurrentTasks then holds at most `concurrent`
|
|
320
|
+
// tasks when prefetch is 0. The next write awaits the queue head.
|
|
321
|
+
assert_eq!(first_error_at, concurrent + 2);
|
|
322
|
+
}
|
|
283
323
|
}
|
|
@@ -817,6 +817,113 @@ impl ExactSizeIterator for BufferChunks {
|
|
|
817
817
|
|
|
818
818
|
impl FusedIterator for BufferChunks {}
|
|
819
819
|
|
|
820
|
+
/// `BufferCursor` is a [`Read`] + [`Seek`] cursor for `Buffer`, analogous to [`std::io::Cursor`].
|
|
821
|
+
///
|
|
822
|
+
/// `BufferCursor` supports seeking over potentially non-contiguous bytes in a Buffer. It is useful when
|
|
823
|
+
/// seekability is required, such as when interfacing with archiving and compression libraries, while
|
|
824
|
+
/// maintaining zero-copy semantics.
|
|
825
|
+
///
|
|
826
|
+
/// ## Notes
|
|
827
|
+
/// - [`BufferCursor`] does not implement [`std::io::Write`], because [`Buffer`] instances are immutable.
|
|
828
|
+
///
|
|
829
|
+
/// ## Features
|
|
830
|
+
/// - [`BufferCursor`] can be used as a [`Read`], [`BufRead`], and [`Seek`] directly.
|
|
831
|
+
/// - [`BufferCursor`] is cheap to read and seek, as it only updates the [`Buffer`] reference count
|
|
832
|
+
/// without additional allocations.
|
|
833
|
+
///
|
|
834
|
+
/// # Examples
|
|
835
|
+
///
|
|
836
|
+
/// ```rust
|
|
837
|
+
/// use bytes::Bytes;
|
|
838
|
+
/// use opendal_core::{Buffer, BufferCursor};
|
|
839
|
+
/// use std::io::{Read, Seek, SeekFrom};
|
|
840
|
+
///
|
|
841
|
+
/// fn test() -> std::io::Result<()> {
|
|
842
|
+
/// let mut cur = BufferCursor::new(Buffer::from(vec![
|
|
843
|
+
/// Bytes::from("abc"),
|
|
844
|
+
/// Bytes::from("def"),
|
|
845
|
+
/// ]));
|
|
846
|
+
///
|
|
847
|
+
/// cur.seek(SeekFrom::Start(3))?;
|
|
848
|
+
///
|
|
849
|
+
/// let mut out = vec![];
|
|
850
|
+
/// cur.read_to_end(&mut out); // def
|
|
851
|
+
///
|
|
852
|
+
/// cur.seek(SeekFrom::Start(0))?;
|
|
853
|
+
///
|
|
854
|
+
/// let mut out = vec![];
|
|
855
|
+
/// cur.read_to_end(&mut out); // abcdef
|
|
856
|
+
///
|
|
857
|
+
/// Ok(())
|
|
858
|
+
/// }
|
|
859
|
+
/// ```
|
|
860
|
+
///
|
|
861
|
+
pub struct BufferCursor {
|
|
862
|
+
data: Buffer,
|
|
863
|
+
view: Buffer,
|
|
864
|
+
pos: u64,
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
impl BufferCursor {
|
|
868
|
+
/// Create a BufferCursor for a Buffer.
|
|
869
|
+
#[inline]
|
|
870
|
+
pub fn new(buffer: Buffer) -> Self {
|
|
871
|
+
Self {
|
|
872
|
+
view: buffer.slice(..),
|
|
873
|
+
data: buffer,
|
|
874
|
+
pos: 0,
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
impl Read for BufferCursor {
|
|
880
|
+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
881
|
+
let size = self.view.read(buf)?;
|
|
882
|
+
self.seek(SeekFrom::Current(size as i64))?;
|
|
883
|
+
Ok(size)
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
impl BufRead for BufferCursor {
|
|
888
|
+
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
|
889
|
+
self.view.fill_buf()
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
fn consume(&mut self, amount: usize) {
|
|
893
|
+
self.pos = self
|
|
894
|
+
.pos
|
|
895
|
+
.saturating_add(amount as u64)
|
|
896
|
+
.min(self.data.len() as u64);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
impl Seek for BufferCursor {
|
|
901
|
+
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
|
902
|
+
let end = self.data.len() as u64;
|
|
903
|
+
match pos {
|
|
904
|
+
SeekFrom::Start(pos) => {
|
|
905
|
+
self.pos = pos.min(end);
|
|
906
|
+
}
|
|
907
|
+
SeekFrom::Current(pos) => {
|
|
908
|
+
if pos.is_negative() {
|
|
909
|
+
self.pos = self.pos.saturating_sub(pos.unsigned_abs());
|
|
910
|
+
} else {
|
|
911
|
+
self.pos = self.pos.saturating_add(pos as u64).min(end);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
SeekFrom::End(pos) => {
|
|
915
|
+
if pos.is_negative() {
|
|
916
|
+
self.pos = end.saturating_sub(pos.unsigned_abs());
|
|
917
|
+
} else {
|
|
918
|
+
self.pos = end.saturating_add(pos as u64).min(end);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
self.view = self.data.slice(self.pos as usize..);
|
|
923
|
+
Ok(self.pos)
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
820
927
|
#[cfg(test)]
|
|
821
928
|
mod tests {
|
|
822
929
|
use std::io::BufRead;
|
|
@@ -1399,4 +1506,28 @@ mod tests {
|
|
|
1399
1506
|
(Bytes::from("cdef"), Bytes::from("cdef"))
|
|
1400
1507
|
);
|
|
1401
1508
|
}
|
|
1509
|
+
|
|
1510
|
+
#[test]
|
|
1511
|
+
fn fuzz_buffer_cursor_seek_and_read() -> io::Result<()> {
|
|
1512
|
+
let (buf, total_size, total_content) = setup_buffer();
|
|
1513
|
+
let mut buf = BufferCursor::new(buf);
|
|
1514
|
+
|
|
1515
|
+
let mut rng = rng();
|
|
1516
|
+
for _ in 0..100 {
|
|
1517
|
+
let pos = match rng.random_range(0..3) {
|
|
1518
|
+
0 => buf.seek(SeekFrom::Start(rng.random_range(0..=total_size as u64)))?,
|
|
1519
|
+
1 => buf.seek(SeekFrom::Current(rng.random_range(
|
|
1520
|
+
-(buf.pos as i64)..=(total_size as i64 - buf.pos as i64),
|
|
1521
|
+
)))?,
|
|
1522
|
+
_ => buf.seek(SeekFrom::End(rng.random_range(-(total_size as i64)..=0)))?,
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
let mut out = vec![];
|
|
1526
|
+
buf.read_to_end(&mut out)?;
|
|
1527
|
+
|
|
1528
|
+
assert_eq!(&out[..], &total_content[pos as usize..]);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
Ok(())
|
|
1532
|
+
}
|
|
1402
1533
|
}
|
|
@@ -107,6 +107,7 @@ impl Deleter {
|
|
|
107
107
|
/// options.
|
|
108
108
|
pub async fn delete(&mut self, input: impl IntoDeleteInput) -> Result<()> {
|
|
109
109
|
let (path, options) = input.into_delete_input();
|
|
110
|
+
let path = normalize_path(&path);
|
|
110
111
|
let op = OpDelete::from_options(&self.capability, options)
|
|
111
112
|
.map_err(|err| err.with_context("service", self.scheme))?;
|
|
112
113
|
self.deleter.delete(&path, op).await?;
|
|
@@ -262,4 +263,16 @@ mod tests {
|
|
|
262
263
|
*flushed
|
|
263
264
|
);
|
|
264
265
|
}
|
|
266
|
+
|
|
267
|
+
#[tokio::test]
|
|
268
|
+
async fn test_delete_normalizes_path() {
|
|
269
|
+
let op = Operator::new(services::Memory::default()).unwrap();
|
|
270
|
+
op.write("dir/file", "data").await.unwrap();
|
|
271
|
+
|
|
272
|
+
let mut deleter = op.deleter().await.unwrap();
|
|
273
|
+
deleter.delete("/dir/file").await.unwrap();
|
|
274
|
+
deleter.close().await.unwrap();
|
|
275
|
+
|
|
276
|
+
assert!(!op.exists("dir/file").await.unwrap());
|
|
277
|
+
}
|
|
265
278
|
}
|