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.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +24 -24
  3. data/Cargo.toml +1 -1
  4. data/DEPENDENCIES.rust.tsv +24 -24
  5. data/core/CHANGELOG.md +9 -1
  6. data/core/Cargo.lock +110 -110
  7. data/core/Cargo.toml +94 -94
  8. data/core/DEPENDENCIES.rust.tsv +12 -12
  9. data/core/benches/types/buffer.rs +61 -0
  10. data/core/benches/vs_fs/Cargo.toml +1 -1
  11. data/core/benches/vs_s3/Cargo.toml +1 -1
  12. data/core/core/CHANGELOG.md +9 -1
  13. data/core/core/src/raw/futures_util.rs +5 -0
  14. data/core/core/src/raw/oio/copy/block_copy.rs +1 -1
  15. data/core/core/src/raw/oio/copy/multipart_copy.rs +1 -1
  16. data/core/core/src/raw/oio/write/block_write.rs +1 -1
  17. data/core/core/src/raw/oio/write/multipart_write.rs +1 -1
  18. data/core/core/src/raw/oio/write/position_write.rs +41 -1
  19. data/core/core/src/types/buffer.rs +131 -0
  20. data/core/core/src/types/delete/deleter.rs +13 -0
  21. data/core/core/src/types/mod.rs +1 -0
  22. data/core/http-transports/reqwest/Cargo.toml +1 -1
  23. data/core/layers/async-backtrace/Cargo.toml +2 -2
  24. data/core/layers/await-tree/Cargo.toml +2 -2
  25. data/core/layers/capability-check/Cargo.toml +2 -2
  26. data/core/layers/chaos/Cargo.toml +2 -2
  27. data/core/layers/concurrent-limit/Cargo.toml +2 -2
  28. data/core/layers/dtrace/Cargo.toml +2 -2
  29. data/core/layers/fastmetrics/Cargo.toml +3 -3
  30. data/core/layers/fastrace/Cargo.toml +2 -2
  31. data/core/layers/foyer/Cargo.toml +2 -2
  32. data/core/layers/hotpath/Cargo.toml +2 -2
  33. data/core/layers/immutable-index/Cargo.toml +2 -2
  34. data/core/layers/logging/Cargo.toml +2 -2
  35. data/core/layers/metrics/Cargo.toml +3 -3
  36. data/core/layers/mime-guess/Cargo.toml +2 -2
  37. data/core/layers/observe-metrics-common/Cargo.toml +1 -1
  38. data/core/layers/otelmetrics/Cargo.toml +3 -3
  39. data/core/layers/oteltrace/Cargo.toml +2 -2
  40. data/core/layers/prometheus/Cargo.toml +3 -3
  41. data/core/layers/prometheus-client/Cargo.toml +3 -3
  42. data/core/layers/retry/Cargo.toml +4 -4
  43. data/core/layers/route/Cargo.toml +3 -3
  44. data/core/layers/tail-cut/Cargo.toml +2 -2
  45. data/core/layers/throttle/Cargo.toml +2 -2
  46. data/core/layers/timeout/Cargo.toml +3 -3
  47. data/core/layers/tracing/Cargo.toml +2 -2
  48. data/core/services/aliyun-drive/Cargo.toml +1 -1
  49. data/core/services/alluxio/Cargo.toml +1 -1
  50. data/core/services/azblob/Cargo.toml +2 -2
  51. data/core/services/azdls/Cargo.toml +2 -2
  52. data/core/services/azfile/Cargo.toml +2 -2
  53. data/core/services/azure-common/Cargo.toml +1 -1
  54. data/core/services/b2/Cargo.toml +1 -1
  55. data/core/services/cacache/Cargo.toml +1 -1
  56. data/core/services/cloudflare-kv/Cargo.toml +1 -1
  57. data/core/services/compfs/Cargo.toml +1 -1
  58. data/core/services/cos/Cargo.toml +1 -1
  59. data/core/services/d1/Cargo.toml +1 -1
  60. data/core/services/dashmap/Cargo.toml +1 -1
  61. data/core/services/dbfs/Cargo.toml +1 -1
  62. data/core/services/dropbox/Cargo.toml +1 -1
  63. data/core/services/etcd/Cargo.toml +1 -1
  64. data/core/services/foundationdb/Cargo.toml +1 -1
  65. data/core/services/foyer/Cargo.toml +3 -3
  66. data/core/services/fs/Cargo.toml +1 -1
  67. data/core/services/ftp/Cargo.toml +1 -1
  68. data/core/services/gcs/Cargo.toml +1 -1
  69. data/core/services/gcs-grpc/Cargo.toml +1 -1
  70. data/core/services/gdrive/Cargo.toml +1 -1
  71. data/core/services/ghac/Cargo.toml +2 -2
  72. data/core/services/github/Cargo.toml +1 -1
  73. data/core/services/goosefs/Cargo.toml +2 -2
  74. data/core/services/goosefs/src/backend.rs +43 -16
  75. data/core/services/goosefs/src/config.rs +4 -1
  76. data/core/services/goosefs/src/docs.md +1 -1
  77. data/core/services/gridfs/Cargo.toml +1 -1
  78. data/core/services/hdfs/Cargo.toml +2 -2
  79. data/core/services/hdfs/src/backend.rs +15 -7
  80. data/core/services/hdfs/src/core.rs +55 -16
  81. data/core/services/hdfs/src/docs.md +9 -1
  82. data/core/services/hdfs-native/Cargo.toml +1 -1
  83. data/core/services/hf/Cargo.toml +5 -2
  84. data/core/services/hf/src/backend.rs +8 -3
  85. data/core/services/hf/src/config.rs +4 -2
  86. data/core/services/hf/src/docs.md +6 -2
  87. data/core/services/hf/src/reader.rs +163 -68
  88. data/core/services/http/Cargo.toml +3 -3
  89. data/core/services/ipfs/Cargo.toml +1 -1
  90. data/core/services/ipmfs/Cargo.toml +1 -1
  91. data/core/services/koofr/Cargo.toml +1 -1
  92. data/core/services/lakefs/Cargo.toml +1 -1
  93. data/core/services/memcached/Cargo.toml +1 -1
  94. data/core/services/mini_moka/Cargo.toml +1 -1
  95. data/core/services/moka/Cargo.toml +1 -1
  96. data/core/services/mongodb/Cargo.toml +1 -1
  97. data/core/services/monoiofs/Cargo.toml +1 -1
  98. data/core/services/mysql/Cargo.toml +1 -1
  99. data/core/services/obs/Cargo.toml +1 -1
  100. data/core/services/onedrive/Cargo.toml +1 -1
  101. data/core/services/opfs/Cargo.toml +1 -1
  102. data/core/services/oss/Cargo.toml +1 -1
  103. data/core/services/oss/src/backend.rs +143 -2
  104. data/core/services/oss/src/docs.md +12 -0
  105. data/core/services/pcloud/Cargo.toml +1 -1
  106. data/core/services/persy/Cargo.toml +1 -1
  107. data/core/services/postgresql/Cargo.toml +1 -1
  108. data/core/services/redb/Cargo.toml +1 -1
  109. data/core/services/redis/Cargo.toml +1 -1
  110. data/core/services/rocksdb/Cargo.toml +1 -1
  111. data/core/services/s3/Cargo.toml +1 -1
  112. data/core/services/seafile/Cargo.toml +1 -1
  113. data/core/services/sftp/Cargo.toml +1 -1
  114. data/core/services/sled/Cargo.toml +1 -1
  115. data/core/services/sqlite/Cargo.toml +1 -1
  116. data/core/services/surrealdb/Cargo.toml +1 -1
  117. data/core/services/swift/Cargo.toml +1 -1
  118. data/core/services/tikv/Cargo.toml +1 -1
  119. data/core/services/tos/Cargo.toml +1 -1
  120. data/core/services/upyun/Cargo.toml +1 -1
  121. data/core/services/vercel-artifacts/Cargo.toml +1 -1
  122. data/core/services/vercel-blob/Cargo.toml +1 -1
  123. data/core/services/webdav/Cargo.toml +1 -1
  124. data/core/services/webdav/src/backend.rs +10 -21
  125. data/core/services/webdav/src/config.rs +5 -14
  126. data/core/services/webhdfs/Cargo.toml +1 -1
  127. data/core/services/yandex-disk/Cargo.toml +1 -1
  128. data/core/testkit/Cargo.toml +4 -4
  129. 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.2"
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.2", default-features = false }
250
- opendal-http-transport-reqwest = { path = "http-transports/reqwest", version = "0.59.2", optional = true, default-features = false }
251
- opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = "0.59.2", optional = true, default-features = false }
252
- opendal-layer-await-tree = { path = "layers/await-tree", version = "0.59.2", optional = true, default-features = false }
253
- opendal-layer-capability-check = { path = "layers/capability-check", version = "0.59.2", optional = true, default-features = false }
254
- opendal-layer-chaos = { path = "layers/chaos", version = "0.59.2", optional = true, default-features = false }
255
- opendal-layer-concurrent-limit = { path = "layers/concurrent-limit", version = "0.59.2", optional = true, default-features = false }
256
- opendal-layer-fastmetrics = { path = "layers/fastmetrics", version = "0.59.2", optional = true, default-features = false }
257
- opendal-layer-fastrace = { path = "layers/fastrace", version = "0.59.2", optional = true, default-features = false }
258
- opendal-layer-foyer = { path = "layers/foyer", version = "0.59.2", optional = true, default-features = false }
259
- opendal-layer-hotpath = { path = "layers/hotpath", version = "0.59.2", optional = true, default-features = false }
260
- opendal-layer-immutable-index = { path = "layers/immutable-index", version = "0.59.2", optional = true, default-features = false }
261
- opendal-layer-logging = { path = "layers/logging", version = "0.59.2", optional = true, default-features = false }
262
- opendal-layer-metrics = { path = "layers/metrics", version = "0.59.2", optional = true, default-features = false }
263
- opendal-layer-mime-guess = { path = "layers/mime-guess", version = "0.59.2", optional = true, default-features = false }
264
- opendal-layer-observe-metrics-common = { path = "layers/observe-metrics-common", version = "0.59.2", optional = true, default-features = false }
265
- opendal-layer-otelmetrics = { path = "layers/otelmetrics", version = "0.59.2", optional = true, default-features = false }
266
- opendal-layer-oteltrace = { path = "layers/oteltrace", version = "0.59.2", optional = true, default-features = false }
267
- opendal-layer-prometheus = { path = "layers/prometheus", version = "0.59.2", optional = true, default-features = false }
268
- opendal-layer-prometheus-client = { path = "layers/prometheus-client", version = "0.59.2", optional = true, default-features = false }
269
- opendal-layer-retry = { path = "layers/retry", version = "0.59.2", optional = true, default-features = false }
270
- opendal-layer-route = { path = "layers/route", version = "0.59.2", optional = true, default-features = false }
271
- opendal-layer-tail-cut = { path = "layers/tail-cut", version = "0.59.2", optional = true, default-features = false }
272
- opendal-layer-throttle = { path = "layers/throttle", version = "0.59.2", optional = true, default-features = false }
273
- opendal-layer-timeout = { path = "layers/timeout", version = "0.59.2", optional = true, default-features = false }
274
- opendal-layer-tracing = { path = "layers/tracing", version = "0.59.2", optional = true, default-features = false }
275
- opendal-service-aliyun-drive = { path = "services/aliyun-drive", version = "0.59.2", optional = true, default-features = false }
276
- opendal-service-alluxio = { path = "services/alluxio", version = "0.59.2", optional = true, default-features = false }
277
- opendal-service-azblob = { path = "services/azblob", version = "0.59.2", optional = true, default-features = false }
278
- opendal-service-azdls = { path = "services/azdls", version = "0.59.2", optional = true, default-features = false }
279
- opendal-service-azfile = { path = "services/azfile", version = "0.59.2", optional = true, default-features = false }
280
- opendal-service-b2 = { path = "services/b2", version = "0.59.2", optional = true, default-features = false }
281
- opendal-service-cacache = { path = "services/cacache", version = "0.59.2", optional = true, default-features = false }
282
- opendal-service-cloudflare-kv = { path = "services/cloudflare-kv", version = "0.59.2", optional = true, default-features = false }
283
- opendal-service-compfs = { path = "services/compfs", version = "0.59.2", optional = true, default-features = false }
284
- opendal-service-cos = { path = "services/cos", version = "0.59.2", optional = true, default-features = false }
285
- opendal-service-d1 = { path = "services/d1", version = "0.59.2", optional = true, default-features = false }
286
- opendal-service-dashmap = { path = "services/dashmap", version = "0.59.2", optional = true, default-features = false }
287
- opendal-service-dbfs = { path = "services/dbfs", version = "0.59.2", optional = true, default-features = false }
288
- opendal-service-dropbox = { path = "services/dropbox", version = "0.59.2", optional = true, default-features = false }
289
- opendal-service-etcd = { path = "services/etcd", version = "0.59.2", optional = true, default-features = false }
290
- opendal-service-foundationdb = { path = "services/foundationdb", version = "0.59.2", optional = true, default-features = false }
291
- opendal-service-foyer = { path = "services/foyer", version = "0.59.2", optional = true, default-features = false }
292
- opendal-service-fs = { path = "services/fs", version = "0.59.2", optional = true, default-features = false }
293
- opendal-service-ftp = { path = "services/ftp", version = "0.59.2", optional = true, default-features = false }
294
- opendal-service-gcs = { path = "services/gcs", version = "0.59.2", optional = true, default-features = false }
295
- opendal-service-gcs-grpc = { path = "services/gcs-grpc", version = "0.59.2", optional = true, default-features = false }
296
- opendal-service-gdrive = { path = "services/gdrive", version = "0.59.2", optional = true, default-features = false }
297
- opendal-service-ghac = { path = "services/ghac", version = "0.59.2", optional = true, default-features = false }
298
- opendal-service-github = { path = "services/github", version = "0.59.2", optional = true, default-features = false }
299
- opendal-service-goosefs = { path = "services/goosefs", version = "0.59.2", optional = true, default-features = false }
300
- opendal-service-gridfs = { path = "services/gridfs", version = "0.59.2", optional = true, default-features = false }
301
- opendal-service-hdfs = { path = "services/hdfs", version = "0.59.2", optional = true, default-features = false }
302
- opendal-service-hdfs-native = { path = "services/hdfs-native", version = "0.59.2", optional = true, default-features = false }
303
- opendal-service-hf = { path = "services/hf", version = "0.59.2", optional = true, default-features = false }
304
- opendal-service-http = { path = "services/http", version = "0.59.2", optional = true, default-features = false }
305
- opendal-service-ipfs = { path = "services/ipfs", version = "0.59.2", optional = true, default-features = false }
306
- opendal-service-ipmfs = { path = "services/ipmfs", version = "0.59.2", optional = true, default-features = false }
307
- opendal-service-koofr = { path = "services/koofr", version = "0.59.2", optional = true, default-features = false }
308
- opendal-service-lakefs = { path = "services/lakefs", version = "0.59.2", optional = true, default-features = false }
309
- opendal-service-memcached = { path = "services/memcached", version = "0.59.2", optional = true, default-features = false }
310
- opendal-service-mini-moka = { path = "services/mini_moka", version = "0.59.2", optional = true, default-features = false }
311
- opendal-service-moka = { path = "services/moka", version = "0.59.2", optional = true, default-features = false }
312
- opendal-service-mongodb = { path = "services/mongodb", version = "0.59.2", optional = true, default-features = false }
313
- opendal-service-monoiofs = { path = "services/monoiofs", version = "0.59.2", optional = true, default-features = false }
314
- opendal-service-mysql = { path = "services/mysql", version = "0.59.2", optional = true, default-features = false }
315
- opendal-service-obs = { path = "services/obs", version = "0.59.2", optional = true, default-features = false }
316
- opendal-service-onedrive = { path = "services/onedrive", version = "0.59.2", optional = true, default-features = false }
317
- opendal-service-oss = { path = "services/oss", version = "0.59.2", optional = true, default-features = false }
318
- opendal-service-pcloud = { path = "services/pcloud", version = "0.59.2", optional = true, default-features = false }
319
- opendal-service-persy = { path = "services/persy", version = "0.59.2", optional = true, default-features = false }
320
- opendal-service-postgresql = { path = "services/postgresql", version = "0.59.2", optional = true, default-features = false }
321
- opendal-service-redb = { path = "services/redb", version = "0.59.2", optional = true, default-features = false }
322
- opendal-service-redis = { path = "services/redis", version = "0.59.2", optional = true, default-features = false }
323
- opendal-service-rocksdb = { path = "services/rocksdb", version = "0.59.2", optional = true, default-features = false }
324
- opendal-service-s3 = { path = "services/s3", version = "0.59.2", optional = true, default-features = false }
325
- opendal-service-seafile = { path = "services/seafile", version = "0.59.2", optional = true, default-features = false }
326
- opendal-service-sftp = { path = "services/sftp", version = "0.59.2", optional = true, default-features = false }
327
- opendal-service-sled = { path = "services/sled", version = "0.59.2", optional = true, default-features = false }
328
- opendal-service-sqlite = { path = "services/sqlite", version = "0.59.2", optional = true, default-features = false }
329
- opendal-service-surrealdb = { path = "services/surrealdb", version = "0.59.2", optional = true, default-features = false }
330
- opendal-service-swift = { path = "services/swift", version = "0.59.2", optional = true, default-features = false }
331
- opendal-service-tikv = { path = "services/tikv", version = "0.59.2", optional = true, default-features = false }
332
- opendal-service-tos = { path = "services/tos", version = "0.59.2", optional = true, default-features = false }
333
- opendal-service-upyun = { path = "services/upyun", version = "0.59.2", optional = true, default-features = false }
334
- opendal-service-vercel-artifacts = { path = "services/vercel-artifacts", version = "0.59.2", optional = true, default-features = false }
335
- opendal-service-vercel-blob = { path = "services/vercel-blob", version = "0.59.2", optional = true, default-features = false }
336
- opendal-service-webdav = { path = "services/webdav", version = "0.59.2", optional = true, default-features = false }
337
- opendal-service-webhdfs = { path = "services/webhdfs", version = "0.59.2", optional = true, default-features = false }
338
- opendal-service-yandex-disk = { path = "services/yandex-disk", version = "0.59.2", optional = true, default-features = false }
339
- opendal-testkit = { path = "testkit", version = "0.59.2", optional = true }
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.2", optional = true, default-features = false }
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.2", optional = true, default-features = false }
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"
@@ -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.2 X
119
- opendal-core@0.59.2 X
120
- opendal-http-transport-reqwest@0.59.2 X
121
- opendal-layer-concurrent-limit@0.59.2 X
122
- opendal-layer-logging@0.59.2 X
123
- opendal-layer-retry@0.59.2 X
124
- opendal-layer-timeout@0.59.2 X
125
- opendal-service-fs@0.59.2 X
126
- opendal-service-goosefs@0.59.2 X
127
- opendal-service-opfs@0.59.2 X
128
- opendal-service-s3@0.59.2 X
129
- opendal-testkit@0.59.2 X
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
+ }
@@ -22,7 +22,7 @@ license = "Apache-2.0"
22
22
  name = "opendal-benchmark-vs-fs"
23
23
  publish = false
24
24
  rust-version = "1.86"
25
- version = "0.59.2"
25
+ version = "0.59.4"
26
26
 
27
27
  [dependencies]
28
28
  criterion = { version = "0.8.2", features = ["async", "async_tokio"] }
@@ -22,7 +22,7 @@ license = "Apache-2.0"
22
22
  name = "opendal-benchmark-vs-s3"
23
23
  publish = false
24
24
  rust-version = "1.86"
25
- version = "0.59.2"
25
+ version = "0.59.4"
26
26
 
27
27
  [dependencies]
28
28
  aws-config = { version = "1.0.1", features = ["behavior-version-latest"] }
@@ -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
- - [Changes since v0.59.1](https://github.com/apache/opendal/compare/v0.59.1...0c360d103f93728889009b6e563bbaf3b0072e71)
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, 8192, |input| {
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, 8192, |input| {
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, 8192, |input| {
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, 8192, |input| {
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, 8192, |input| {
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
  }