opendal 0.1.9 → 0.1.11

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 (566) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +89 -56
  3. data/Cargo.toml +1 -1
  4. data/DEPENDENCIES.rust.tsv +55 -41
  5. data/LICENSE +201 -0
  6. data/LICENSE-MPL-2.0.txt +373 -0
  7. data/NOTICE +5 -0
  8. data/core/CHANGELOG.md +175 -0
  9. data/core/Cargo.lock +225 -298
  10. data/core/Cargo.toml +100 -94
  11. data/core/DEPENDENCIES.rust.tsv +44 -73
  12. data/core/benches/metadata/README.md +21 -0
  13. data/core/benches/metadata/main.rs +541 -0
  14. data/core/benches/vs_fs/Cargo.toml +1 -1
  15. data/core/benches/vs_s3/Cargo.toml +1 -1
  16. data/core/core/Cargo.toml +7 -2
  17. data/core/core/src/blocking/delete.rs +5 -1
  18. data/core/core/src/blocking/operator.rs +12 -0
  19. data/core/core/src/blocking/read/std_reader.rs +25 -0
  20. data/core/core/src/docs/concepts.rs +70 -94
  21. data/core/core/src/docs/internals/accessor.rs +62 -293
  22. data/core/core/src/docs/internals/layer.rs +43 -59
  23. data/core/core/src/docs/internals/mod.rs +21 -23
  24. data/core/core/src/docs/mod.rs +10 -6
  25. data/core/core/src/docs/performance/concurrent_write.md +92 -55
  26. data/core/core/src/docs/performance/http_optimization.md +120 -104
  27. data/core/core/src/docs/performance/mod.rs +8 -6
  28. data/core/core/src/docs/rfcs/5485_conditional_reader.md +4 -0
  29. data/core/core/src/docs/rfcs/7182_restore_api.md +139 -557
  30. data/core/core/src/docs/rfcs/7945_limited_read.md +210 -0
  31. data/core/core/src/docs/rfcs/7948_s3_provider_presets.md +254 -0
  32. data/core/core/src/docs/rfcs/8109_writer_copy_from.md +330 -0
  33. data/core/core/src/docs/rfcs/8145_conflict_error_kind.md +210 -0
  34. data/core/core/src/docs/rfcs/8147_write_if_not_changed.md +233 -0
  35. data/core/core/src/docs/rfcs/8188_compose_api.md +292 -0
  36. data/core/core/src/docs/rfcs/8194_compact_metadata_and_operation_args.md +444 -0
  37. data/core/core/src/docs/rfcs/README.md +14 -3
  38. data/core/core/src/docs/rfcs/mod.rs +46 -22
  39. data/core/core/src/docs/specs/README.md +34 -0
  40. data/core/core/src/docs/specs/conditional-operations.md +156 -0
  41. data/core/core/src/docs/specs/metadata.md +63 -0
  42. data/core/core/src/docs/specs/mod.rs +26 -0
  43. data/core/core/src/docs/upgrade.md +114 -1
  44. data/core/core/src/layers/capability_override.rs +15 -2
  45. data/core/core/src/layers/complete.rs +347 -43
  46. data/core/core/src/layers/correctness_check.rs +718 -51
  47. data/core/core/src/layers/error_context.rs +76 -2
  48. data/core/core/src/layers/simulate.rs +91 -28
  49. data/core/core/src/lib.rs +1 -0
  50. data/core/core/src/raw/accessor.rs +91 -15
  51. data/core/core/src/raw/enum_utils.rs +7 -0
  52. data/core/core/src/raw/http_util/header.rs +22 -17
  53. data/core/core/src/raw/oio/compose/api.rs +92 -0
  54. data/core/core/src/raw/oio/compose/mod.rs +19 -0
  55. data/core/core/src/raw/oio/copy/api.rs +3 -3
  56. data/core/core/src/raw/oio/copy/block_copy.rs +32 -4
  57. data/core/core/src/raw/oio/copy/multipart_copy.rs +36 -7
  58. data/core/core/src/raw/oio/entry.rs +48 -22
  59. data/core/core/src/raw/oio/list/flat_list.rs +1 -1
  60. data/core/core/src/raw/oio/list/hierarchy_list.rs +3 -2
  61. data/core/core/src/raw/oio/mod.rs +3 -0
  62. data/core/core/src/raw/oio/read/position_read.rs +1 -1
  63. data/core/core/src/raw/oio/write/api.rs +40 -0
  64. data/core/core/src/raw/oio/write/append_write.rs +4 -4
  65. data/core/core/src/raw/oio/write/block_write.rs +2 -2
  66. data/core/core/src/raw/oio/write/multipart_write.rs +181 -48
  67. data/core/core/src/raw/oio/write/position_write.rs +1 -1
  68. data/core/core/src/raw/operation.rs +6 -0
  69. data/core/core/src/raw/ops.rs +1191 -456
  70. data/core/core/src/raw/rps.rs +11 -0
  71. data/core/core/src/raw/time.rs +14 -3
  72. data/core/core/src/services/memory/backend.rs +5 -10
  73. data/core/core/src/services/memory/lister.rs +4 -4
  74. data/core/core/src/services/memory/writer.rs +7 -6
  75. data/core/core/src/types/buffer.rs +102 -12
  76. data/core/core/src/types/bytes_range.rs +20 -1
  77. data/core/core/src/types/capability.rs +65 -0
  78. data/core/core/src/types/compact.rs +329 -0
  79. data/core/core/src/types/compose/composer.rs +183 -0
  80. data/core/core/src/types/compose/input.rs +57 -0
  81. data/core/core/src/types/compose/mod.rs +23 -0
  82. data/core/core/src/types/context/read.rs +16 -11
  83. data/core/core/src/types/context/write.rs +150 -2
  84. data/core/core/src/types/copy.rs +5 -3
  85. data/core/core/src/types/delete/deleter.rs +20 -12
  86. data/core/core/src/types/delete/input.rs +22 -64
  87. data/core/core/src/types/delete/mod.rs +0 -1
  88. data/core/core/src/types/entry.rs +8 -14
  89. data/core/core/src/types/error.rs +28 -11
  90. data/core/core/src/types/metadata.rs +709 -322
  91. data/core/core/src/types/mod.rs +9 -1
  92. data/core/core/src/types/operator/operator.rs +278 -29
  93. data/core/core/src/types/operator/operator_futures.rs +466 -105
  94. data/core/core/src/types/options.rs +631 -158
  95. data/core/core/src/types/read/futures_async_reader.rs +663 -50
  96. data/core/core/src/types/read/reader.rs +23 -5
  97. data/core/core/src/types/write/futures_async_writer.rs +27 -0
  98. data/core/core/src/types/write/writer.rs +47 -5
  99. data/core/http-transports/reqwest/Cargo.toml +1 -1
  100. data/core/layers/async-backtrace/Cargo.toml +2 -2
  101. data/core/layers/async-backtrace/src/lib.rs +21 -2
  102. data/core/layers/await-tree/Cargo.toml +2 -2
  103. data/core/layers/await-tree/src/lib.rs +25 -2
  104. data/core/layers/capability-check/Cargo.toml +2 -2
  105. data/core/layers/capability-check/src/lib.rs +98 -10
  106. data/core/layers/chaos/Cargo.toml +2 -2
  107. data/core/layers/chaos/src/lib.rs +18 -3
  108. data/core/layers/concurrent-limit/Cargo.toml +3 -3
  109. data/core/layers/concurrent-limit/src/lib.rs +53 -13
  110. data/core/layers/dtrace/Cargo.toml +2 -2
  111. data/core/layers/dtrace/src/lib.rs +29 -2
  112. data/core/layers/fastmetrics/Cargo.toml +3 -3
  113. data/core/layers/fastrace/Cargo.toml +2 -2
  114. data/core/layers/fastrace/src/lib.rs +28 -2
  115. data/core/layers/foyer/Cargo.toml +2 -2
  116. data/core/layers/foyer/src/full.rs +16 -19
  117. data/core/layers/foyer/src/lib.rs +67 -14
  118. data/core/layers/hotpath/Cargo.toml +2 -2
  119. data/core/layers/hotpath/src/lib.rs +20 -2
  120. data/core/layers/immutable-index/Cargo.toml +2 -2
  121. data/core/layers/immutable-index/src/lib.rs +48 -24
  122. data/core/layers/logging/Cargo.toml +2 -2
  123. data/core/layers/logging/src/lib.rs +46 -2
  124. data/core/layers/metrics/Cargo.toml +3 -3
  125. data/core/layers/mime-guess/Cargo.toml +2 -2
  126. data/core/layers/mime-guess/src/lib.rs +31 -4
  127. data/core/layers/observe-metrics-common/Cargo.toml +2 -2
  128. data/core/layers/observe-metrics-common/src/lib.rs +55 -2
  129. data/core/layers/otelmetrics/Cargo.toml +3 -3
  130. data/core/layers/oteltrace/Cargo.toml +2 -2
  131. data/core/layers/oteltrace/src/lib.rs +27 -2
  132. data/core/layers/prometheus/Cargo.toml +3 -3
  133. data/core/layers/prometheus-client/Cargo.toml +3 -3
  134. data/core/layers/retry/Cargo.toml +4 -4
  135. data/core/layers/retry/src/lib.rs +76 -19
  136. data/core/layers/route/Cargo.toml +3 -3
  137. data/core/layers/route/src/lib.rs +34 -7
  138. data/core/layers/tail-cut/Cargo.toml +2 -2
  139. data/core/layers/tail-cut/src/lib.rs +28 -2
  140. data/core/layers/throttle/Cargo.toml +2 -2
  141. data/core/layers/throttle/src/lib.rs +19 -2
  142. data/core/layers/timeout/Cargo.toml +3 -3
  143. data/core/layers/timeout/src/lib.rs +38 -13
  144. data/core/layers/tracing/Cargo.toml +2 -2
  145. data/core/layers/tracing/src/lib.rs +24 -3
  146. data/core/services/aliyun-drive/Cargo.toml +2 -2
  147. data/core/services/aliyun-drive/src/backend.rs +34 -24
  148. data/core/services/aliyun-drive/src/core.rs +143 -54
  149. data/core/services/aliyun-drive/src/lister.rs +19 -18
  150. data/core/services/aliyun-drive/src/reader.rs +4 -1
  151. data/core/services/aliyun-drive/src/writer.rs +3 -3
  152. data/core/services/alluxio/Cargo.toml +1 -1
  153. data/core/services/alluxio/src/backend.rs +1 -1
  154. data/core/services/alluxio/src/core.rs +113 -94
  155. data/core/services/alluxio/src/reader.rs +7 -3
  156. data/core/services/alluxio/src/writer.rs +2 -2
  157. data/core/services/azblob/Cargo.toml +2 -2
  158. data/core/services/azblob/src/backend.rs +17 -9
  159. data/core/services/azblob/src/copier.rs +41 -15
  160. data/core/services/azblob/src/core.rs +372 -135
  161. data/core/services/azblob/src/deleter.rs +41 -18
  162. data/core/services/azblob/src/lister.rs +16 -10
  163. data/core/services/azblob/src/reader.rs +4 -1
  164. data/core/services/azblob/src/writer.rs +48 -15
  165. data/core/services/azdls/Cargo.toml +3 -3
  166. data/core/services/azdls/src/backend.rs +45 -15
  167. data/core/services/azdls/src/config.rs +4 -1
  168. data/core/services/azdls/src/core.rs +276 -87
  169. data/core/services/azdls/src/deleter.rs +13 -4
  170. data/core/services/azdls/src/lister.rs +18 -12
  171. data/core/services/azdls/src/reader.rs +6 -2
  172. data/core/services/azdls/src/writer.rs +44 -23
  173. data/core/services/azfile/Cargo.toml +2 -2
  174. data/core/services/azfile/src/backend.rs +24 -8
  175. data/core/services/azfile/src/core.rs +195 -77
  176. data/core/services/azfile/src/deleter.rs +8 -1
  177. data/core/services/azfile/src/lister.rs +20 -14
  178. data/core/services/azfile/src/reader.rs +5 -2
  179. data/core/services/azfile/src/writer.rs +27 -15
  180. data/core/services/azure-common/Cargo.toml +1 -1
  181. data/core/services/b2/Cargo.toml +2 -2
  182. data/core/services/b2/src/backend.rs +30 -11
  183. data/core/services/b2/src/core.rs +134 -120
  184. data/core/services/b2/src/deleter.rs +1 -1
  185. data/core/services/b2/src/lister.rs +5 -2
  186. data/core/services/b2/src/reader.rs +5 -2
  187. data/core/services/b2/src/writer.rs +29 -12
  188. data/core/services/cacache/Cargo.toml +1 -1
  189. data/core/services/cacache/src/backend.rs +4 -5
  190. data/core/services/cacache/src/reader.rs +4 -1
  191. data/core/services/cacache/src/writer.rs +6 -2
  192. data/core/services/cloudflare-kv/Cargo.toml +1 -1
  193. data/core/services/cloudflare-kv/src/backend.rs +26 -15
  194. data/core/services/cloudflare-kv/src/config.rs +13 -2
  195. data/core/services/cloudflare-kv/src/core.rs +62 -56
  196. data/core/services/cloudflare-kv/src/deleter.rs +12 -3
  197. data/core/services/cloudflare-kv/src/lister.rs +66 -17
  198. data/core/services/cloudflare-kv/src/reader.rs +14 -9
  199. data/core/services/cloudflare-kv/src/writer.rs +10 -7
  200. data/core/services/compfs/Cargo.toml +1 -1
  201. data/core/services/compfs/src/backend.rs +11 -7
  202. data/core/services/compfs/src/lister.rs +7 -7
  203. data/core/services/compfs/src/writer.rs +1 -1
  204. data/core/services/cos/Cargo.toml +1 -1
  205. data/core/services/cos/src/backend.rs +129 -16
  206. data/core/services/cos/src/core.rs +198 -80
  207. data/core/services/cos/src/deleter.rs +4 -1
  208. data/core/services/cos/src/lister.rs +42 -27
  209. data/core/services/cos/src/reader.rs +6 -2
  210. data/core/services/cos/src/writer.rs +45 -21
  211. data/core/services/d1/Cargo.toml +1 -1
  212. data/core/services/d1/src/backend.rs +6 -5
  213. data/core/services/d1/src/core.rs +79 -63
  214. data/core/services/d1/src/reader.rs +4 -1
  215. data/core/services/d1/src/writer.rs +6 -2
  216. data/core/services/dashmap/Cargo.toml +1 -1
  217. data/core/services/dashmap/src/backend.rs +2 -2
  218. data/core/services/dashmap/src/reader.rs +4 -1
  219. data/core/services/dashmap/src/writer.rs +11 -8
  220. data/core/services/dbfs/Cargo.toml +1 -1
  221. data/core/services/dbfs/src/backend.rs +21 -15
  222. data/core/services/dbfs/src/core.rs +65 -60
  223. data/core/services/dbfs/src/deleter.rs +4 -1
  224. data/core/services/dbfs/src/lister.rs +10 -10
  225. data/core/services/dbfs/src/writer.rs +6 -3
  226. data/core/services/dropbox/Cargo.toml +2 -2
  227. data/core/services/dropbox/src/backend.rs +30 -23
  228. data/core/services/dropbox/src/core.rs +65 -63
  229. data/core/services/dropbox/src/deleter.rs +1 -1
  230. data/core/services/dropbox/src/lister.rs +17 -8
  231. data/core/services/dropbox/src/reader.rs +4 -1
  232. data/core/services/dropbox/src/writer.rs +13 -10
  233. data/core/services/etcd/Cargo.toml +1 -1
  234. data/core/services/etcd/src/backend.rs +8 -5
  235. data/core/services/etcd/src/core.rs +5 -11
  236. data/core/services/etcd/src/lister.rs +6 -1
  237. data/core/services/etcd/src/reader.rs +4 -1
  238. data/core/services/etcd/src/writer.rs +6 -3
  239. data/core/services/foundationdb/Cargo.toml +1 -1
  240. data/core/services/foundationdb/src/backend.rs +6 -5
  241. data/core/services/foundationdb/src/reader.rs +4 -1
  242. data/core/services/foundationdb/src/writer.rs +6 -2
  243. data/core/services/foyer/Cargo.toml +3 -3
  244. data/core/services/foyer/src/backend.rs +6 -5
  245. data/core/services/foyer/src/reader.rs +4 -1
  246. data/core/services/foyer/src/writer.rs +6 -2
  247. data/core/services/fs/Cargo.toml +1 -1
  248. data/core/services/fs/src/backend.rs +4 -3
  249. data/core/services/fs/src/core.rs +44 -26
  250. data/core/services/fs/src/lister.rs +9 -6
  251. data/core/services/fs/src/writer.rs +20 -13
  252. data/core/services/ftp/Cargo.toml +4 -6
  253. data/core/services/ftp/src/backend.rs +9 -5
  254. data/core/services/ftp/src/core.rs +9 -7
  255. data/core/services/ftp/src/lister.rs +7 -8
  256. data/core/services/ftp/src/reader.rs +3 -3
  257. data/core/services/ftp/src/writer.rs +3 -3
  258. data/core/services/gcs/Cargo.toml +4 -2
  259. data/core/services/gcs/src/backend.rs +53 -7
  260. data/core/services/gcs/src/composer.rs +705 -0
  261. data/core/services/gcs/src/copier.rs +14 -4
  262. data/core/services/gcs/src/core.rs +828 -124
  263. data/core/services/gcs/src/deleter.rs +33 -18
  264. data/core/services/gcs/src/lib.rs +1 -0
  265. data/core/services/gcs/src/lister.rs +21 -12
  266. data/core/services/gcs/src/reader.rs +12 -5
  267. data/core/services/gcs/src/writer.rs +632 -10
  268. data/core/services/gcs-grpc/Cargo.toml +58 -0
  269. data/core/services/gcs-grpc/README.md +19 -0
  270. data/core/services/gcs-grpc/proto/README.md +23 -0
  271. data/core/services/gcs-grpc/proto/google/storage/v2/storage.proto +171 -0
  272. data/core/services/gcs-grpc/proto/upstream-descriptor.bin +0 -0
  273. data/core/services/gcs-grpc/src/backend.rs +449 -0
  274. data/core/services/gcs-grpc/src/config.rs +116 -0
  275. data/core/services/gcs-grpc/src/copier.rs +98 -0
  276. data/core/services/gcs-grpc/src/core.rs +298 -0
  277. data/core/services/gcs-grpc/src/deleter.rs +65 -0
  278. data/core/services/gcs-grpc/src/docs.md +19 -0
  279. data/core/services/gcs-grpc/src/generated/google.storage.v2.rs +541 -0
  280. data/core/services/gcs-grpc/src/generated/mod.rs +24 -0
  281. data/core/services/gcs-grpc/src/lib.rs +43 -0
  282. data/core/services/gcs-grpc/src/lister.rs +125 -0
  283. data/core/services/gcs-grpc/src/reader.rs +140 -0
  284. data/core/services/gcs-grpc/src/writer.rs +780 -0
  285. data/core/services/gdrive/Cargo.toml +2 -2
  286. data/core/services/gdrive/src/backend.rs +123 -69
  287. data/core/services/gdrive/src/core.rs +87 -69
  288. data/core/services/gdrive/src/deleter.rs +8 -2
  289. data/core/services/gdrive/src/lister.rs +38 -26
  290. data/core/services/gdrive/src/path_index.rs +2 -2
  291. data/core/services/gdrive/src/reader.rs +9 -3
  292. data/core/services/gdrive/src/writer.rs +13 -7
  293. data/core/services/ghac/Cargo.toml +2 -2
  294. data/core/services/ghac/src/backend.rs +5 -2
  295. data/core/services/ghac/src/core.rs +59 -37
  296. data/core/services/ghac/src/reader.rs +5 -2
  297. data/core/services/ghac/src/writer.rs +16 -6
  298. data/core/services/github/Cargo.toml +1 -1
  299. data/core/services/github/src/backend.rs +16 -8
  300. data/core/services/github/src/core.rs +88 -76
  301. data/core/services/github/src/lister.rs +17 -15
  302. data/core/services/github/src/reader.rs +5 -2
  303. data/core/services/github/src/writer.rs +12 -6
  304. data/core/services/goosefs/Cargo.toml +2 -2
  305. data/core/services/goosefs/src/backend.rs +2 -2
  306. data/core/services/goosefs/src/core.rs +291 -208
  307. data/core/services/goosefs/src/docs.md +3 -0
  308. data/core/services/goosefs/src/lister.rs +2 -3
  309. data/core/services/goosefs/src/reader.rs +7 -3
  310. data/core/services/goosefs/src/writer.rs +21 -10
  311. data/core/services/goosefs/tests/safe_conditional_put.rs +37 -0
  312. data/core/services/gridfs/Cargo.toml +2 -2
  313. data/core/services/gridfs/src/backend.rs +12 -8
  314. data/core/services/gridfs/src/core.rs +1 -1
  315. data/core/services/gridfs/src/reader.rs +4 -1
  316. data/core/services/gridfs/src/writer.rs +6 -2
  317. data/core/services/hdfs/Cargo.toml +1 -1
  318. data/core/services/hdfs/src/backend.rs +1 -1
  319. data/core/services/hdfs/src/core.rs +7 -4
  320. data/core/services/hdfs/src/lister.rs +7 -9
  321. data/core/services/hdfs/src/writer.rs +5 -1
  322. data/core/services/hdfs-native/Cargo.toml +1 -1
  323. data/core/services/hdfs-native/src/backend.rs +1 -1
  324. data/core/services/hdfs-native/src/core.rs +44 -50
  325. data/core/services/hdfs-native/src/lister.rs +8 -10
  326. data/core/services/hdfs-native/src/writer.rs +5 -1
  327. data/core/services/hf/Cargo.toml +4 -3
  328. data/core/services/hf/src/backend.rs +4 -3
  329. data/core/services/hf/src/core.rs +907 -153
  330. data/core/services/hf/src/lister.rs +16 -6
  331. data/core/services/hf/src/reader.rs +377 -57
  332. data/core/services/hf/src/writer.rs +6 -2
  333. data/core/services/http/Cargo.toml +3 -3
  334. data/core/services/http/src/backend.rs +8 -6
  335. data/core/services/http/src/core.rs +57 -35
  336. data/core/services/http/src/reader.rs +5 -2
  337. data/core/services/ipfs/Cargo.toml +1 -1
  338. data/core/services/ipfs/src/backend.rs +20 -9
  339. data/core/services/ipfs/src/core.rs +43 -34
  340. data/core/services/ipfs/src/reader.rs +5 -2
  341. data/core/services/ipmfs/Cargo.toml +1 -1
  342. data/core/services/ipmfs/src/backend.rs +17 -8
  343. data/core/services/ipmfs/src/core.rs +66 -60
  344. data/core/services/ipmfs/src/deleter.rs +5 -2
  345. data/core/services/ipmfs/src/lister.rs +15 -12
  346. data/core/services/ipmfs/src/reader.rs +5 -2
  347. data/core/services/ipmfs/src/writer.rs +6 -3
  348. data/core/services/koofr/Cargo.toml +2 -2
  349. data/core/services/koofr/src/backend.rs +46 -17
  350. data/core/services/koofr/src/core.rs +64 -48
  351. data/core/services/koofr/src/deleter.rs +4 -1
  352. data/core/services/koofr/src/lister.rs +11 -10
  353. data/core/services/koofr/src/reader.rs +5 -2
  354. data/core/services/koofr/src/writer.rs +13 -7
  355. data/core/services/lakefs/Cargo.toml +1 -1
  356. data/core/services/lakefs/src/backend.rs +25 -8
  357. data/core/services/lakefs/src/core.rs +79 -73
  358. data/core/services/lakefs/src/deleter.rs +4 -1
  359. data/core/services/lakefs/src/lister.rs +17 -14
  360. data/core/services/lakefs/src/reader.rs +5 -2
  361. data/core/services/lakefs/src/writer.rs +11 -10
  362. data/core/services/memcached/Cargo.toml +1 -1
  363. data/core/services/memcached/src/backend.rs +57 -7
  364. data/core/services/memcached/src/config.rs +13 -2
  365. data/core/services/memcached/src/core.rs +11 -1
  366. data/core/services/memcached/src/reader.rs +4 -1
  367. data/core/services/memcached/src/writer.rs +6 -2
  368. data/core/services/mini_moka/Cargo.toml +1 -1
  369. data/core/services/mini_moka/src/backend.rs +8 -8
  370. data/core/services/mini_moka/src/reader.rs +4 -1
  371. data/core/services/mini_moka/src/writer.rs +11 -7
  372. data/core/services/moka/Cargo.toml +1 -1
  373. data/core/services/moka/src/backend.rs +7 -7
  374. data/core/services/moka/src/reader.rs +4 -1
  375. data/core/services/moka/src/writer.rs +10 -6
  376. data/core/services/mongodb/Cargo.toml +2 -2
  377. data/core/services/mongodb/src/backend.rs +7 -6
  378. data/core/services/mongodb/src/core.rs +1 -1
  379. data/core/services/mongodb/src/reader.rs +4 -1
  380. data/core/services/mongodb/src/writer.rs +6 -2
  381. data/core/services/monoiofs/Cargo.toml +2 -2
  382. data/core/services/monoiofs/src/backend.rs +16 -10
  383. data/core/services/monoiofs/src/core.rs +8 -9
  384. data/core/services/monoiofs/src/reader.rs +8 -10
  385. data/core/services/monoiofs/src/writer.rs +19 -24
  386. data/core/services/mysql/Cargo.toml +2 -2
  387. data/core/services/mysql/src/backend.rs +7 -6
  388. data/core/services/mysql/src/core.rs +1 -1
  389. data/core/services/mysql/src/lister.rs +7 -3
  390. data/core/services/mysql/src/reader.rs +4 -1
  391. data/core/services/mysql/src/writer.rs +6 -2
  392. data/core/services/obs/Cargo.toml +1 -1
  393. data/core/services/obs/src/backend.rs +29 -11
  394. data/core/services/obs/src/core.rs +81 -82
  395. data/core/services/obs/src/deleter.rs +4 -1
  396. data/core/services/obs/src/lister.rs +12 -5
  397. data/core/services/obs/src/reader.rs +5 -2
  398. data/core/services/obs/src/writer.rs +40 -19
  399. data/core/services/onedrive/Cargo.toml +2 -2
  400. data/core/services/onedrive/src/backend.rs +30 -21
  401. data/core/services/onedrive/src/config.rs +2 -2
  402. data/core/services/onedrive/src/core.rs +191 -90
  403. data/core/services/onedrive/src/deleter.rs +5 -2
  404. data/core/services/onedrive/src/graph_model.rs +10 -51
  405. data/core/services/onedrive/src/lister.rs +60 -24
  406. data/core/services/onedrive/src/reader.rs +17 -2
  407. data/core/services/onedrive/src/writer.rs +26 -15
  408. data/core/services/opfs/Cargo.toml +1 -1
  409. data/core/services/opfs/src/backend.rs +6 -13
  410. data/core/services/opfs/src/core.rs +33 -37
  411. data/core/services/opfs/src/lister.rs +4 -4
  412. data/core/services/opfs/src/writer.rs +1 -3
  413. data/core/services/oss/Cargo.toml +1 -1
  414. data/core/services/oss/src/backend.rs +40 -8
  415. data/core/services/oss/src/core.rs +192 -92
  416. data/core/services/oss/src/deleter.rs +16 -6
  417. data/core/services/oss/src/lister.rs +43 -27
  418. data/core/services/oss/src/reader.rs +6 -2
  419. data/core/services/oss/src/writer.rs +40 -22
  420. data/core/services/pcloud/Cargo.toml +1 -1
  421. data/core/services/pcloud/src/backend.rs +40 -6
  422. data/core/services/pcloud/src/core.rs +80 -66
  423. data/core/services/pcloud/src/deleter.rs +8 -1
  424. data/core/services/pcloud/src/lister.rs +4 -1
  425. data/core/services/pcloud/src/reader.rs +5 -2
  426. data/core/services/pcloud/src/writer.rs +6 -3
  427. data/core/services/persy/Cargo.toml +1 -1
  428. data/core/services/persy/src/backend.rs +6 -5
  429. data/core/services/persy/src/core.rs +60 -15
  430. data/core/services/persy/src/reader.rs +4 -1
  431. data/core/services/persy/src/writer.rs +6 -2
  432. data/core/services/postgresql/Cargo.toml +2 -2
  433. data/core/services/postgresql/src/backend.rs +7 -6
  434. data/core/services/postgresql/src/core.rs +1 -1
  435. data/core/services/postgresql/src/reader.rs +4 -1
  436. data/core/services/postgresql/src/writer.rs +6 -2
  437. data/core/services/redb/Cargo.toml +1 -1
  438. data/core/services/redb/src/backend.rs +6 -5
  439. data/core/services/redb/src/reader.rs +4 -1
  440. data/core/services/redb/src/writer.rs +6 -2
  441. data/core/services/redis/Cargo.toml +1 -1
  442. data/core/services/redis/src/backend.rs +18 -8
  443. data/core/services/redis/src/config.rs +13 -2
  444. data/core/services/redis/src/reader.rs +8 -4
  445. data/core/services/redis/src/writer.rs +6 -2
  446. data/core/services/rocksdb/Cargo.toml +1 -1
  447. data/core/services/rocksdb/src/backend.rs +6 -5
  448. data/core/services/rocksdb/src/lister.rs +6 -5
  449. data/core/services/rocksdb/src/reader.rs +4 -1
  450. data/core/services/rocksdb/src/writer.rs +6 -2
  451. data/core/services/s3/Cargo.toml +5 -4
  452. data/core/services/s3/src/backend.rs +995 -39
  453. data/core/services/s3/src/compatible_services.md +57 -0
  454. data/core/services/s3/src/config.rs +16 -0
  455. data/core/services/s3/src/copier.rs +190 -55
  456. data/core/services/s3/src/core.rs +299 -190
  457. data/core/services/s3/src/deleter.rs +26 -7
  458. data/core/services/s3/src/docs.md +57 -0
  459. data/core/services/s3/src/lister.rs +55 -36
  460. data/core/services/s3/src/reader.rs +22 -2
  461. data/core/services/s3/src/writer.rs +154 -32
  462. data/core/services/seafile/Cargo.toml +2 -2
  463. data/core/services/seafile/src/backend.rs +3 -3
  464. data/core/services/seafile/src/core.rs +105 -79
  465. data/core/services/seafile/src/lister.rs +11 -8
  466. data/core/services/seafile/src/reader.rs +5 -2
  467. data/core/services/seafile/src/writer.rs +6 -3
  468. data/core/services/sftp/Cargo.toml +1 -1
  469. data/core/services/sftp/src/backend.rs +19 -4
  470. data/core/services/sftp/src/core.rs +51 -46
  471. data/core/services/sftp/src/lister.rs +4 -4
  472. data/core/services/sftp/src/writer.rs +1 -1
  473. data/core/services/sled/Cargo.toml +1 -1
  474. data/core/services/sled/src/backend.rs +6 -5
  475. data/core/services/sled/src/core.rs +28 -6
  476. data/core/services/sled/src/lister.rs +6 -5
  477. data/core/services/sled/src/reader.rs +4 -1
  478. data/core/services/sled/src/writer.rs +6 -2
  479. data/core/services/sqlite/Cargo.toml +2 -2
  480. data/core/services/sqlite/src/backend.rs +12 -7
  481. data/core/services/sqlite/src/core.rs +3 -3
  482. data/core/services/sqlite/src/reader.rs +4 -1
  483. data/core/services/sqlite/src/writer.rs +7 -3
  484. data/core/services/surrealdb/Cargo.toml +2 -2
  485. data/core/services/surrealdb/src/backend.rs +7 -6
  486. data/core/services/surrealdb/src/core.rs +1 -1
  487. data/core/services/surrealdb/src/reader.rs +4 -1
  488. data/core/services/surrealdb/src/writer.rs +6 -2
  489. data/core/services/swift/Cargo.toml +1 -1
  490. data/core/services/swift/src/backend.rs +38 -8
  491. data/core/services/swift/src/core.rs +63 -67
  492. data/core/services/swift/src/deleter.rs +8 -2
  493. data/core/services/swift/src/lister.rs +11 -8
  494. data/core/services/swift/src/reader.rs +5 -2
  495. data/core/services/swift/src/writer.rs +17 -8
  496. data/core/services/tikv/Cargo.toml +2 -2
  497. data/core/services/tikv/src/backend.rs +7 -6
  498. data/core/services/tikv/src/core.rs +31 -14
  499. data/core/services/tikv/src/reader.rs +4 -1
  500. data/core/services/tikv/src/writer.rs +6 -2
  501. data/core/services/tos/Cargo.toml +2 -2
  502. data/core/services/tos/src/backend.rs +45 -21
  503. data/core/services/tos/src/copier.rs +44 -17
  504. data/core/services/tos/src/core.rs +147 -117
  505. data/core/services/tos/src/deleter.rs +9 -3
  506. data/core/services/tos/src/docs.md +1 -1
  507. data/core/services/tos/src/lister.rs +43 -28
  508. data/core/services/tos/src/reader.rs +5 -2
  509. data/core/services/tos/src/writer.rs +37 -16
  510. data/core/services/upyun/Cargo.toml +1 -1
  511. data/core/services/upyun/src/backend.rs +30 -7
  512. data/core/services/upyun/src/core.rs +122 -87
  513. data/core/services/upyun/src/deleter.rs +4 -1
  514. data/core/services/upyun/src/lister.rs +10 -10
  515. data/core/services/upyun/src/reader.rs +5 -2
  516. data/core/services/upyun/src/writer.rs +19 -7
  517. data/core/services/vercel-artifacts/Cargo.toml +1 -1
  518. data/core/services/vercel-artifacts/src/backend.rs +6 -3
  519. data/core/services/vercel-artifacts/src/core.rs +32 -27
  520. data/core/services/vercel-artifacts/src/reader.rs +5 -2
  521. data/core/services/vercel-artifacts/src/writer.rs +6 -3
  522. data/core/services/vercel-blob/Cargo.toml +1 -1
  523. data/core/services/vercel-blob/src/backend.rs +23 -6
  524. data/core/services/vercel-blob/src/core.rs +92 -81
  525. data/core/services/vercel-blob/src/lister.rs +12 -3
  526. data/core/services/vercel-blob/src/reader.rs +5 -2
  527. data/core/services/vercel-blob/src/writer.rs +19 -7
  528. data/core/services/webdav/Cargo.toml +2 -2
  529. data/core/services/webdav/src/backend.rs +25 -5
  530. data/core/services/webdav/src/core.rs +116 -59
  531. data/core/services/webdav/src/deleter.rs +4 -1
  532. data/core/services/webdav/src/lister.rs +4 -1
  533. data/core/services/webdav/src/reader.rs +6 -2
  534. data/core/services/webdav/src/writer.rs +17 -7
  535. data/core/services/webhdfs/Cargo.toml +2 -2
  536. data/core/services/webhdfs/src/backend.rs +24 -11
  537. data/core/services/webhdfs/src/core.rs +99 -98
  538. data/core/services/webhdfs/src/deleter.rs +5 -2
  539. data/core/services/webhdfs/src/lister.rs +21 -9
  540. data/core/services/webhdfs/src/reader.rs +5 -2
  541. data/core/services/webhdfs/src/writer.rs +49 -14
  542. data/core/services/yandex-disk/Cargo.toml +1 -1
  543. data/core/services/yandex-disk/src/backend.rs +28 -6
  544. data/core/services/yandex-disk/src/core.rs +97 -79
  545. data/core/services/yandex-disk/src/deleter.rs +4 -1
  546. data/core/services/yandex-disk/src/lister.rs +25 -9
  547. data/core/services/yandex-disk/src/reader.rs +5 -2
  548. data/core/services/yandex-disk/src/writer.rs +6 -3
  549. data/core/src/lib.rs +5 -0
  550. data/core/testkit/Cargo.toml +4 -4
  551. data/core/testkit/src/utils.rs +53 -8
  552. data/core/tests/behavior/async_compose.rs +297 -0
  553. data/core/tests/behavior/async_copy.rs +162 -1
  554. data/core/tests/behavior/async_delete.rs +364 -3
  555. data/core/tests/behavior/async_read.rs +86 -0
  556. data/core/tests/behavior/async_restore.rs +162 -0
  557. data/core/tests/behavior/async_stat.rs +90 -0
  558. data/core/tests/behavior/async_write.rs +330 -2
  559. data/core/tests/behavior/main.rs +4 -0
  560. data/core/upgrade.md +114 -1
  561. data/src/capability.rs +0 -1
  562. data/src/io.rs +0 -1
  563. data/src/lister.rs +0 -1
  564. data/src/metadata.rs +0 -1
  565. data/src/operator_info.rs +0 -1
  566. metadata +44 -2
@@ -15,101 +15,104 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- //! The core concepts of OpenDAL's public API.
18
+ //! The core concepts of OpenDAL's Rust API.
19
19
  //!
20
- //! OpenDAL provides a unified abstraction for accessing storage services.
20
+ //! OpenDAL gives applications one storage API across services. Rust
21
+ //! applications use four concepts: a service describes the storage backend, a
22
+ //! builder configures it, an operator exposes operations, and layers add
23
+ //! behavior around those operations.
21
24
  //!
22
- //! Public users mostly work with three concepts:
25
+ //! For the language-independent model shared by every OpenDAL binding, see the
26
+ //! [OpenDAL concepts guide](https://opendal.apache.org/docs/concepts/).
23
27
  //!
24
- //! - [`Builder`]: configures and builds a storage service.
25
- //! - [`Operator`]: owns a service stack and exposes storage operations such as
26
- //! `read`, `write`, and `list`.
27
- //! - [`Layer`][crate::raw::Layer]: wraps an operator's service stack or runtime
28
- //! resources to add behavior such as retry, timeout, tracing, and metrics.
28
+ //! # Service and builder
29
29
  //!
30
- //! If you are interested in internal implementation details, please have a look at [`internals`][super::internals].
30
+ //! A **service** is a storage backend such as S3, Google Cloud Storage, a
31
+ //! local filesystem, or an in-memory store. Each service supports a different
32
+ //! set of operations and optional features.
31
33
  //!
32
- //! # Builder
33
- //!
34
- //! A [`Builder`] configures and creates the underlying storage service. Service
35
- //! crates expose builders through [`services`][crate::services], for example
36
- //! [`services::Memory`][crate::services::Memory].
34
+ //! A [`Builder`] collects one service's configuration and constructs its
35
+ //! implementation. The [`services`][crate::services] module exposes concrete
36
+ //! builders, while [`Operator::new`] turns a builder into a ready-to-use
37
+ //! operator.
37
38
  //!
38
39
  //! ```text
39
- //! ┌─────────┐ build() ┌─────────┐
40
- //! │ Builder ├────────────►│ Service │
41
- //! └─────────┘ └─────────┘
40
+ //! configuration -> builder -> service -> operator
42
41
  //! ```
43
42
  //!
44
43
  //! ```no_run
44
+ //! # use opendal_core::Result;
45
+ //! use opendal_core::Operator;
45
46
  //! use opendal_core::services::Memory;
46
47
  //!
48
+ //! # fn test() -> Result<()> {
47
49
  //! let builder = Memory::default();
50
+ //! let op = Operator::new(builder)?;
51
+ //! # let _ = op;
52
+ //! # Ok(())
53
+ //! # }
48
54
  //! ```
49
55
  //!
56
+ //! OpenDAL does not make every service support every operation. Applications
57
+ //! can inspect the operator's effective [`Capability`] before using an
58
+ //! optional operation or option.
59
+ //!
50
60
  //! # Operator
51
61
  //!
52
- //! An [`Operator`] is the public handle for a storage service stack. It stores:
62
+ //! An [`Operator`] is the public handle for one configured service and root.
63
+ //! It normalizes paths, validates options against effective capabilities, runs
64
+ //! the configured layers, and dispatches each operation to the service.
53
65
  //!
54
- //! - a base service created from the builder.
55
- //! - a base [`OperationContext`] with runtime resources such as HTTP transport
56
- //! and executor.
57
- //! - an ordered list of layers.
58
- //! - the composed service and context used by storage operations.
66
+ //! Operators are cheap to clone, contain no caller-visible lifetime or service
67
+ //! type parameter, and can be shared across threads. A clone refers to the
68
+ //! same composed service stack. Methods that add a layer or replace runtime
69
+ //! resources return a new operator; existing clones and in-flight operations
70
+ //! keep their current stack.
59
71
  //!
60
- //! ```text
61
- //! ┌─────────┐ Operator::new ┌────────────────────────────┐
62
- //! │ Builder ├──────────────────►│ Operator │
63
- //! └─────────┘ │ - base service │
64
- //! │ - base OperationContext │
65
- //! │ - layers │
66
- //! │ - composed service/context │
67
- //! └────────────────────────────┘
68
- //! ```
72
+ //! # Operation
69
73
  //!
70
- //! `Operator::new` returns a ready-to-use operator. There is no separate
71
- //! `finish` step.
74
+ //! Operations are storage actions such as `read`, `write`, `stat`, `list`,
75
+ //! `delete`, `copy`, and `rename`. Convenience methods use default options,
76
+ //! while the corresponding `_with` methods expose operation-specific options.
72
77
  //!
73
78
  //! ```no_run
74
79
  //! # use opendal_core::Result;
75
- //! use opendal_core::services::Memory;
76
80
  //! use opendal_core::Operator;
81
+ //! use opendal_core::services::Memory;
77
82
  //!
78
- //! # fn test() -> Result<()> {
79
- //! let builder = Memory::default();
80
- //!
81
- //! let op = Operator::new(builder)?;
83
+ //! # async fn test() -> Result<()> {
84
+ //! let op = Operator::new(Memory::default())?;
85
+ //! let bs = op.read("abc").await?;
86
+ //! # let _ = bs;
82
87
  //! # Ok(())
83
88
  //! # }
84
89
  //! ```
85
90
  //!
86
- //! - `Operator` is cheap to clone because it stores shared handles internally.
87
- //! - `Operator` has no generic parameters or lifetimes, so it is easy to pass
88
- //! through application code.
89
- //! - `Operator` is `Send` and `Sync`, so it can be shared across threads.
90
- //! - Methods that change layers or runtime resources return a new operator;
91
- //! existing clones and in-flight operations keep using their current composed
92
- //! service and context.
91
+ //! OpenDAL normalizes every path relative to the operator's root. `/`
92
+ //! represents the root, a trailing `/` represents a directory, and any other
93
+ //! normalized path represents a file. Operation documentation defines the
94
+ //! observable behavior and errors. [Specifications][super::specs] define
95
+ //! portable contracts that span multiple operations and services.
96
+ //!
97
+ //! # Layer and operation context
93
98
  //!
94
- //! # Runtime resources and layers
99
+ //! A [`Layer`][crate::raw::Layer] adds cross-cutting behavior such as retry,
100
+ //! timeout, tracing, or metrics. Layers form an ordered stack around a
101
+ //! service.
95
102
  //!
96
- //! [`OperationContext`] carries runtime resources from the operator to services,
97
- //! such as [`HttpTransporter`][crate::HttpTransporter] and [`Executor`][crate::Executor].
98
- //! Operation arguments such as ranges, versions, and concurrency limits stay in
99
- //! the `Op*` argument structs used by each operation.
103
+ //! An [`OperationContext`] carries runtime resources such as the HTTP
104
+ //! transport and executor from the operator to the service.
105
+ //! Operation-specific values such as ranges, versions, conditions, and
106
+ //! concurrency remain in that operation's options.
100
107
  //!
101
- //! Use [`Operator::with_context`] to replace the base context. Use
102
- //! [`Operator::layer`] to append a layer. In both cases, OpenDAL replays the full
103
- //! layer list from the base service and base context to produce a fresh composed
104
- //! service and context.
108
+ //! Adding a layer with [`Operator::layer`] or replacing the base context with
109
+ //! [`Operator::with_context`] rebuilds both the service stack and the composed
110
+ //! context from the same ordered layer list:
105
111
  //!
106
112
  //! ```text
107
- //! base service ─┐
108
- //! ├─ layer replay ─► composed service ─┐
109
- //! base context ─┘ ├─► operation dispatch
110
- //! │ srv.read(&ctx, ...)
111
- //! ▼
112
- //! composed context
113
+ //! base service -----+ +-> composed service --+
114
+ //! +-> ordered layers --+ +-> operation
115
+ //! base context -----+ +-> composed context --+
113
116
  //! ```
114
117
  //!
115
118
  //! ```no_run
@@ -129,40 +132,13 @@
129
132
  //! # }
130
133
  //! ```
131
134
  //!
132
- //! # Operations
133
- //!
134
- //! After creating an operator, use it to run operations on normalized paths.
135
- //!
136
- //! ```text
137
- //! ┌──────────────┐
138
- //! ┌────────►│ read("abc") │
139
- //! │ └──────────────┘
140
- //! ┌───────────┐ │
141
- //! │ Operator │ │ ┌──────────────┐
142
- //! │ ┌───────┐ ├────┼────────►│ write("def") │
143
- //! │ │Service│ │ │ └──────────────┘
144
- //! └─┴───────┴─┘ │
145
- //! │ ┌──────────────┐
146
- //! └────────►│ list("ghi/") │
147
- //! └──────────────┘
148
- //! ```
149
- //!
150
- //! We can read data with given path in this way:
151
- //!
152
- //! ```no_run
153
- //! # use opendal_core::Result;
154
- //! use opendal_core::services::Memory;
155
- //! use opendal_core::Operator;
156
- //!
157
- //! # async fn test() -> Result<()> {
158
- //! let builder = Memory::default();
159
- //!
160
- //! let op = Operator::new(builder)?;
161
- //! let bs: Vec<u8> = op.read("abc").await?;
162
- //! # Ok(())
163
- //! # }
164
- //! ```
135
+ //! Most applications only need the public [`Operator`] API. Service and layer
136
+ //! authors should continue with the [internals][super::internals] guide.
165
137
  //!
166
138
  //! [`Builder`]: crate::Builder
167
139
  //! [`Operator`]: crate::Operator
140
+ //! [`Operator::new`]: crate::Operator::new
141
+ //! [`Operator::layer`]: crate::Operator::layer
142
+ //! [`Operator::with_context`]: crate::Operator::with_context
143
+ //! [`Capability`]: crate::Capability
168
144
  //! [`OperationContext`]: crate::OperationContext
@@ -15,318 +15,87 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
 
18
- //! The internal implementation details of [`Service`].
18
+ //! Implementing a service.
19
19
  //!
20
- //! [`Service`] is the core trait of OpenDAL's raw API. We operate
21
- //! underlying storage services via APIs provided by [`Service`].
20
+ //! Every OpenDAL backend implements the raw [`Service`] trait. A service owns
21
+ //! protocol-specific request construction and response handling. The operator
22
+ //! owns path normalization, option validation, layer composition, and
23
+ //! dispatch.
22
24
  //!
23
- //! # Introduction
25
+ //! Service crates live under `core/services/<name>/`. Their public builder and
26
+ //! configuration types construct a typed backend; the backend then implements
27
+ //! [`Service`].
24
28
  //!
25
- //! [`Service`] can be split in the following parts:
29
+ //! # Service identity and capabilities
26
30
  //!
27
- //! ```ignore
28
- //! // <----------Trait Bound-------------->
29
- //! pub trait Service: Send + Sync + Debug + Unpin + 'static {
30
- //! fn info(&self) -> ServiceInfo;
31
- //! fn capability(&self) -> Capability;
31
+ //! [`Service::info`] returns immutable identity such as the scheme, root, and
32
+ //! namespace name. Runtime resources do not belong in [`ServiceInfo`];
33
+ //! services read them from [`OperationContext`].
32
34
  //!
33
- //! type Reader: oio::Read;
34
- //! type Writer: oio::Write;
35
- //! type Lister: oio::List;
36
- //! type Deleter: oio::Delete;
37
- //! type Copier: oio::Copy;
35
+ //! [`Service::capability`] reports the behavior implemented by that service
36
+ //! stack. Set an operation or option capability only when the implementation
37
+ //! satisfies the corresponding public contract. Operators reject options whose
38
+ //! required capability is absent.
38
39
  //!
39
- //! fn read(
40
- //! &self,
41
- //! ctx: &OperationContext,
42
- //! path: &str,
43
- //! args: OpRead,
44
- //! ) -> impl Future<Output = Result<Self::Reader>> + MaybeSend;
45
- //! }
46
- //! ```
47
- //!
48
- //! Let's go deep into [`Service`] line by line.
49
- //!
50
- //! ## Trait Bound
51
- //!
52
- //! First we will read the declaration of [`Service`] trait:
53
- //!
54
- //! ```ignore
55
- //! pub trait Service: Send + Sync + Debug + Unpin + 'static {}
56
- //! ```
57
- //!
58
- //! There are many trait boundings here. For now, [`Service`] requires the following bound:
59
- //!
60
- //! - [`Send`]: Allow user to send between threads without extra wrapper.
61
- //! - [`Sync`]: Allow user to sync between threads without extra lock.
62
- //! - [`Debug`][std::fmt::Debug]: Allow users to print underlying debug information of service.
63
- //! - [`Unpin`]: Make sure `Service` can be safely moved after being pinned, so users don't need to `Pin<Box<A>>`.
64
- //! - `'static`: Make sure `Service` is not a short-time reference, allow users to use `Service` in closures and futures without playing with lifetime.
65
- //!
66
- //! Implementer of `Service` should take care of the following things:
67
- //!
68
- //! - Implement `Debug` for backend, but don't leak credentials.
69
- //! - Make sure the backend is `Send` and `Sync`, wrap the internal struct with `Arc<Mutex<T>>` if necessary.
70
- //!
71
- //! ## Associated Type
72
- //!
73
- //! The middle block of [`Service`] is our associated types. We require
74
- //! implementers to specify concrete operation body types, avoiding extra
75
- //! dynamic dispatch inside the backend and typed service wrappers.
76
- //!
77
- //! [`Service`] has five associated types so far:
78
- //!
79
- //! - `Reader`: reader returned by `read` operation.
80
- //! - `Writer`: writer returned by `write` operation.
81
- //! - `Lister`: lister returned by `list` operation.
82
- //! - `Deleter`: deleter returned by `delete` operation.
83
- //! - `Copier`: copier returned by `copy` operation.
84
- //!
85
- //! Backend implementers should take care of the following things:
86
- //!
87
- //! - Return concrete operation body types instead of dynamic trait objects like `oio::Reader`.
88
- //! - Use `()` as the type if the operation is not supported.
89
- //! - Implement every operation method; unsupported operations should return
90
- //! [`ErrorKind::Unsupported`] explicitly.
91
- //!
92
- //! Runtime service wrappers that already receive a [`Servicer`] can forward the
93
- //! erased `oio::*` body types, but the original backend should not erase itself.
94
- //!
95
- //! OpenDAL erases these associated types at the [`ServiceDyn`] boundary.
96
- //! [`Servicer`] is `Arc<dyn ServiceDyn>` and is the handle used by
97
- //! [`Operator`] and runtime layer composition. This keeps backend and typed
98
- //! layer implementations concrete, while the composed operator stack can be
99
- //! stored and cloned through one object-safe service handle.
100
- //!
101
- //! ## API Style
102
- //!
103
- //! Every API of [`Service`] follows the same style:
104
- //!
105
- //! - All APIs have a unique [`Operation`] and [`Capability`]
106
- //! - All APIs are orthogonal and do not overlap with each other
107
- //! - Most APIs accept [`OperationContext`], `path` and `OpXxx`, and returns `RpXxx` with concrete operation bodies.
108
- //! - Most APIs have `async` and `blocking` variants, they share the same semantics but may have different underlying implementations.
109
- //!
110
- //! [`OperationContext`] carries operator resources composed by operator layers,
111
- //! such as HTTP client and executor. Backend implementations should use this
112
- //! context instead of storing mutable operator resources in [`ServiceInfo`].
113
- //!
114
- //! [`Service`] declares immutable identity facts via [`ServiceInfo`] and
115
- //! operation capability via [`Service::capability`]:
116
- //!
117
- //! ```ignore
118
- //! impl Service for MyBackend {
119
- //! type Reader = MyReader;
120
- //! type Writer = ();
121
- //! type Lister = ();
122
- //! type Deleter = ();
123
- //! type Copier = ();
124
- //!
125
- //! fn info(&self) -> ServiceInfo {
126
- //! ServiceInfo::new(MY_SCHEME, "/", "")
127
- //! }
128
- //!
129
- //! fn capability(&self) -> Capability {
130
- //! Capability {
131
- //! read: true,
132
- //! write: true,
133
- //! ..Default::default()
134
- //! }
135
- //! }
136
- //! }
137
- //! ```
138
- //!
139
- //! Now that you have mastered [`Service`], let's go and implement our own backend!
140
- //!
141
- //! # Tutorial
40
+ //! # Operation body types
142
41
  //!
143
- //! This tutorial implements a `duck` storage service that sends API
144
- //! requests to a super-powered duck. Gagaga!
42
+ //! [`Service`] uses associated types for operation bodies:
145
43
  //!
146
- //! ## Scheme
147
- //!
148
- //! First of all, let's pick a good scheme for our duck service. The
149
- //! scheme should be unique and easy to understand. Normally we should
150
- //! use its formal name.
151
- //!
152
- //! For example, we will use `s3` for AWS S3 Compatible Storage Service
153
- //! instead of `aws` or `awss3`. This is because there are many storage
154
- //! vendors that provide s3-like RESTful APIs, and our s3 service is
155
- //! implemented to support all of them, not just AWS S3.
156
- //!
157
- //! Obviously, we can use `duck` as scheme, let's add a new constant string:
158
- //!
159
- //! ```ignore
160
- //! pub const DUCK_SCHEME: &str = "duck";
44
+ //! ```text
45
+ //! type Reader: oio::Read;
46
+ //! type Writer: oio::Write;
47
+ //! type Lister: oio::List;
48
+ //! type Deleter: oio::Delete;
49
+ //! type Copier: oio::Copy;
161
50
  //! ```
162
51
  //!
163
- //! ## Builder
52
+ //! A backend returns concrete body types so its implementation and typed
53
+ //! wrappers do not pay for dynamic dispatch. Use `()` for an unsupported body
54
+ //! type and return [`ErrorKind::Unsupported`] from the corresponding operation
55
+ //! entry point.
164
56
  //!
165
- //! Then we can implement a builder for the duck service. The [`Builder`]
166
- //! will provide APIs for users to configure, and they will create an
167
- //! instance of a particular service.
57
+ //! OpenDAL erases these types once, at [`ServiceDyn`]. [`Servicer`] is
58
+ //! `Arc<dyn ServiceDyn>` and is the handle used by operators and runtime layer
59
+ //! composition. A wrapper that receives a [`Servicer`] may forward erased
60
+ //! `oio::*` bodies, but a backend should keep its own bodies concrete.
168
61
  //!
169
- //! Let's create a `backend` mod under `services/duck` directory, and adding the following code.
62
+ //! # Operation methods
170
63
  //!
171
- //! ```ignore
172
- //! use crate::raw::*;
173
- //! use crate::*;
64
+ //! Each operation method receives normalized paths, an [`OperationContext`],
65
+ //! and operation-specific arguments. The context supplies layer-composed
66
+ //! runtime resources such as the HTTP transport and executor. Options such as
67
+ //! ranges, versions, conditions, and concurrency remain in the operation
68
+ //! arguments.
174
69
  //!
175
- //! /// Duck Storage Service support. Gagaga!
176
- //! ///
177
- //! /// # Capabilities
178
- //! ///
179
- //! /// This service can be used to:
180
- //! ///
181
- //! /// - [x] read
182
- //! /// - [ ] write
183
- //! /// - [ ] list
184
- //! /// - [ ] presign
185
- //! ///
186
- //! /// # Configuration
187
- //! ///
188
- //! /// - `root`: Set the work dir for backend.
189
- //! ///
190
- //! /// ## Via Builder
191
- //! ///
192
- //! /// ```no_run
193
- //! /// use std::sync::Arc;
194
- //! ///
195
- //! /// use anyhow::Result;
196
- //! /// use opendal_core::services::Duck;
197
- //! /// use opendal_core::Operator;
198
- //! ///
199
- //! /// #[tokio::main]
200
- //! /// async fn main() -> Result<()> {
201
- //! /// // Create Duck backend builder.
202
- //! /// let mut builder = DuckBuilder::default();
203
- //! /// // Set the root for duck, all operations will happen under this root.
204
- //! /// //
205
- //! /// // NOTE: the root must be absolute path.
206
- //! /// builder.root("/path/to/dir");
207
- //! ///
208
- //! /// let op: Operator = Operator::new(builder)?;
209
- //! ///
210
- //! /// Ok(())
211
- //! /// }
212
- //! /// ```
213
- //! #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
214
- //! #[serde(default)]
215
- //! #[non_exhaustive]
216
- //! pub struct DuckConfig {
217
- //! pub root: Option<String>,
218
- //! }
70
+ //! An implementation must:
219
71
  //!
220
- //! #[derive(Default, Clone)]
221
- //! pub struct DuckBuilder {
222
- //! config: DuckConfig,
223
- //! }
224
- //! ```
225
- //!
226
- //! Now let's implement the required APIs for `DuckConfig`:
72
+ //! - Map every advertised option to the native request without silently
73
+ //! dropping it.
74
+ //! - Preserve the operation's public success, error, and atomicity contract.
75
+ //! - Return structured OpenDAL errors with the correct [`ErrorKind`] and
76
+ //! useful context.
77
+ //! - Keep credentials and other secrets out of `Debug` output and errors.
78
+ //! - Forward cancellation and cleanup to protocol-specific readers, writers,
79
+ //! deleters, and copiers.
227
80
  //!
228
- //! ```ignore
229
- //! impl Configurator for DuckConfig {
230
- //! type Builder = DuckBuilder;
231
- //!
232
- //! fn into_builder(self) -> Self::Builder {
233
- //! DuckBuilder { config: self }
234
- //! }
235
- //! }
236
- //! ```
81
+ //! # Adding or changing a service
237
82
  //!
238
- //! Note that `DuckBuilder` is part of our public API, so it needs to be
239
- //! documented. And any changes you make will directly affect users, so
240
- //! please take it seriously. Otherwise, you will be hunted down by many
241
- //! angry ducks.
83
+ //! Keep configuration, request construction, operation bodies, and error
84
+ //! parsing at their existing service boundaries. Update the facade feature and
85
+ //! service registration when the service must be available through the
86
+ //! `opendal` crate.
242
87
  //!
243
- //! Then, we can implement required APIs for `DuckBuilder`:
244
- //!
245
- //! ```ignore
246
- //! impl DuckBuilder {
247
- //! /// Set root of this backend.
248
- //! ///
249
- //! /// All operations will happen under this root.
250
- //! pub fn root(&mut self, root: &str) -> &mut Self {
251
- //! self.config.root = if root.is_empty() {
252
- //! None
253
- //! } else {
254
- //! Some(root.to_string())
255
- //! };
256
- //!
257
- //! self
258
- //! }
259
- //! }
260
- //!
261
- //! impl Builder for DuckBuilder {
262
- //! type Config = DuckConfig;
263
- //!
264
- //! fn build(self) -> Result<impl Service> {
265
- //! debug!("backend build started: {:?}", &self);
266
- //!
267
- //! let root = normalize_root(&self.config.root.clone().unwrap_or_default());
268
- //! debug!("backend use root {}", &root);
269
- //!
270
- //! Ok(DuckBackend { root })
271
- //! }
272
- //! }
273
- //! ```
274
- //!
275
- //! `DuckBuilder` is ready now, let's try to play with real ducks!
276
- //!
277
- //! ## Backend
278
- //!
279
- //! I'm sure you can see it already: `DuckBuilder` will build a
280
- //! `DuckBackend` that implements [`Service`]. The backend is what we used
281
- //! to communicate with the super-powered ducks!
282
- //!
283
- //! Let's keep adding more code under `backend.rs`:
284
- //!
285
- //! ```ignore
286
- //! /// Duck storage service backend
287
- //! #[derive(Clone, Debug)]
288
- //! pub struct DuckBackend {
289
- //! root: String,
290
- //! }
291
- //!
292
- //! impl Service for DuckBackend {
293
- //! type Reader = DuckReader;
294
- //! type Writer = ();
295
- //! type Lister = ();
296
- //! type Deleter = ();
297
- //! type Copier = ();
298
- //!
299
- //! fn info(&self) -> ServiceInfo {
300
- //! ServiceInfo::new(DUCK_SCHEME, &self.root, "")
301
- //! }
302
- //!
303
- //! fn capability(&self) -> Capability {
304
- //! Capability {
305
- //! read: true,
306
- //! ..Default::default()
307
- //! }
308
- //! }
309
- //!
310
- //! fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
311
- //! gagaga!()
312
- //! }
313
- //! }
314
- //! ```
315
- //!
316
- //! Congratulations, we have implemented a [`Service`] that can talk to
317
- //! Super Power Ducks!
318
- //!
319
- //! What!? There are no Super Power Ducks? So sad, but never mind, we have
320
- //! really powerful storage services [here](https://github.com/apache/opendal/issues/5). Welcome to pick one to implement. I promise you won't
321
- //! have to `gagaga!()` this time.
88
+ //! Before advertising new behavior, reproduce it against the actual service
89
+ //! and run the matching capability-gated behavior tests. Protocol
90
+ //! documentation, emulators, and fabricated responses can explain an
91
+ //! implementation, but they do not establish real-service conformance.
322
92
  //!
323
93
  //! [`Service`]: crate::raw::Service
94
+ //! [`Service::info`]: crate::raw::Service::info
95
+ //! [`Service::capability`]: crate::raw::Service::capability
96
+ //! [`ServiceInfo`]: crate::raw::ServiceInfo
324
97
  //! [`ServiceDyn`]: crate::raw::ServiceDyn
325
98
  //! [`Servicer`]: crate::raw::Servicer
326
- //! [`Operation`]: crate::raw::Operation
327
- //! [`Capability`]: crate::Capability
328
- //! [`ServiceInfo`]: crate::raw::ServiceInfo
329
- //! [`OperationContext`]: crate::raw::OperationContext
330
- //! [`Operator`]: crate::Operator
331
- //! [`Builder`]: crate::Builder
332
- //! [`Configurator`]: crate::Configurator
99
+ //! [`OperationContext`]: crate::OperationContext
100
+ //! [`ErrorKind`]: crate::ErrorKind
101
+ //! [`ErrorKind::Unsupported`]: crate::ErrorKind::Unsupported