opendal 0.1.6.pre.rc.1

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 (809) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +20 -0
  3. data/.tool-versions +1 -0
  4. data/.yardopts +1 -0
  5. data/Cargo.toml +65 -0
  6. data/DEPENDENCIES.md +9 -0
  7. data/DEPENDENCIES.rust.tsv +277 -0
  8. data/Gemfile +35 -0
  9. data/README.md +159 -0
  10. data/Rakefile +149 -0
  11. data/build.rs +22 -0
  12. data/core/CHANGELOG.md +4929 -0
  13. data/core/CONTRIBUTING.md +61 -0
  14. data/core/Cargo.lock +10259 -0
  15. data/core/Cargo.toml +437 -0
  16. data/core/DEPENDENCIES.md +3 -0
  17. data/core/DEPENDENCIES.rust.tsv +185 -0
  18. data/core/LICENSE +201 -0
  19. data/core/README.md +228 -0
  20. data/core/benches/README.md +18 -0
  21. data/core/benches/ops/README.md +26 -0
  22. data/core/benches/ops/main.rs +25 -0
  23. data/core/benches/ops/read.rs +100 -0
  24. data/core/benches/ops/utils.rs +59 -0
  25. data/core/benches/ops/write.rs +106 -0
  26. data/core/benches/types/README.md +9 -0
  27. data/core/benches/types/buffer.rs +114 -0
  28. data/core/benches/types/main.rs +23 -0
  29. data/core/benches/types/tasks.rs +64 -0
  30. data/core/benches/vs_fs/Cargo.toml +32 -0
  31. data/core/benches/vs_fs/README.md +35 -0
  32. data/core/benches/vs_fs/src/main.rs +83 -0
  33. data/core/benches/vs_s3/Cargo.toml +38 -0
  34. data/core/benches/vs_s3/README.md +55 -0
  35. data/core/benches/vs_s3/src/main.rs +123 -0
  36. data/core/edge/README.md +3 -0
  37. data/core/edge/file_write_on_full_disk/Cargo.toml +31 -0
  38. data/core/edge/file_write_on_full_disk/README.md +14 -0
  39. data/core/edge/file_write_on_full_disk/src/main.rs +43 -0
  40. data/core/edge/s3_aws_assume_role_with_web_identity/Cargo.toml +30 -0
  41. data/core/edge/s3_aws_assume_role_with_web_identity/README.md +18 -0
  42. data/core/edge/s3_aws_assume_role_with_web_identity/src/main.rs +34 -0
  43. data/core/edge/s3_read_on_wasm/.gitignore +3 -0
  44. data/core/edge/s3_read_on_wasm/Cargo.toml +38 -0
  45. data/core/edge/s3_read_on_wasm/README.md +42 -0
  46. data/core/edge/s3_read_on_wasm/src/lib.rs +60 -0
  47. data/core/edge/s3_read_on_wasm/webdriver.json +15 -0
  48. data/core/examples/README.md +23 -0
  49. data/core/examples/basic/Cargo.toml +29 -0
  50. data/core/examples/basic/README.md +15 -0
  51. data/core/examples/basic/src/main.rs +51 -0
  52. data/core/examples/concurrent-upload/Cargo.toml +29 -0
  53. data/core/examples/concurrent-upload/README.md +15 -0
  54. data/core/examples/concurrent-upload/src/main.rs +68 -0
  55. data/core/examples/multipart-upload/Cargo.toml +29 -0
  56. data/core/examples/multipart-upload/README.md +15 -0
  57. data/core/examples/multipart-upload/src/main.rs +56 -0
  58. data/core/fuzz/.gitignore +5 -0
  59. data/core/fuzz/Cargo.toml +92 -0
  60. data/core/fuzz/README.md +68 -0
  61. data/core/fuzz/fuzz_reader.rs +102 -0
  62. data/core/fuzz/fuzz_writer.rs +123 -0
  63. data/core/src/blocking/delete.rs +74 -0
  64. data/core/src/blocking/list.rs +71 -0
  65. data/core/src/blocking/mod.rs +33 -0
  66. data/core/src/blocking/operator.rs +729 -0
  67. data/core/src/blocking/read/buffer_iterator.rs +66 -0
  68. data/core/src/blocking/read/mod.rs +27 -0
  69. data/core/src/blocking/read/reader.rs +124 -0
  70. data/core/src/blocking/read/std_bytes_iterator.rs +69 -0
  71. data/core/src/blocking/read/std_reader.rs +95 -0
  72. data/core/src/blocking/write/mod.rs +22 -0
  73. data/core/src/blocking/write/std_writer.rs +82 -0
  74. data/core/src/blocking/write/writer.rs +109 -0
  75. data/core/src/docs/comparisons/mod.rs +30 -0
  76. data/core/src/docs/comparisons/vs_object_store.md +183 -0
  77. data/core/src/docs/concepts.rs +135 -0
  78. data/core/src/docs/internals/accessor.rs +306 -0
  79. data/core/src/docs/internals/layer.rs +42 -0
  80. data/core/src/docs/internals/mod.rs +62 -0
  81. data/core/src/docs/mod.rs +43 -0
  82. data/core/src/docs/performance/concurrent_write.md +101 -0
  83. data/core/src/docs/performance/http_optimization.md +124 -0
  84. data/core/src/docs/performance/mod.rs +32 -0
  85. data/core/src/docs/rfcs/0000_example.md +74 -0
  86. data/core/src/docs/rfcs/0000_foyer_integration.md +111 -0
  87. data/core/src/docs/rfcs/0041_object_native_api.md +185 -0
  88. data/core/src/docs/rfcs/0044_error_handle.md +198 -0
  89. data/core/src/docs/rfcs/0057_auto_region.md +160 -0
  90. data/core/src/docs/rfcs/0069_object_stream.md +145 -0
  91. data/core/src/docs/rfcs/0090_limited_reader.md +155 -0
  92. data/core/src/docs/rfcs/0112_path_normalization.md +79 -0
  93. data/core/src/docs/rfcs/0191_async_streaming_io.md +328 -0
  94. data/core/src/docs/rfcs/0203_remove_credential.md +96 -0
  95. data/core/src/docs/rfcs/0221_create_dir.md +89 -0
  96. data/core/src/docs/rfcs/0247_retryable_error.md +87 -0
  97. data/core/src/docs/rfcs/0293_object_id.md +67 -0
  98. data/core/src/docs/rfcs/0337_dir_entry.md +191 -0
  99. data/core/src/docs/rfcs/0409_accessor_capabilities.md +67 -0
  100. data/core/src/docs/rfcs/0413_presign.md +154 -0
  101. data/core/src/docs/rfcs/0423_command_line_interface.md +268 -0
  102. data/core/src/docs/rfcs/0429_init_from_iter.md +107 -0
  103. data/core/src/docs/rfcs/0438_multipart.md +163 -0
  104. data/core/src/docs/rfcs/0443_gateway.md +73 -0
  105. data/core/src/docs/rfcs/0501_new_builder.md +111 -0
  106. data/core/src/docs/rfcs/0554_write_refactor.md +96 -0
  107. data/core/src/docs/rfcs/0561_list_metadata_reuse.md +210 -0
  108. data/core/src/docs/rfcs/0599_blocking_api.md +157 -0
  109. data/core/src/docs/rfcs/0623_redis_service.md +300 -0
  110. data/core/src/docs/rfcs/0627_split_capabilities.md +89 -0
  111. data/core/src/docs/rfcs/0661_path_in_accessor.md +126 -0
  112. data/core/src/docs/rfcs/0793_generic_kv_services.md +209 -0
  113. data/core/src/docs/rfcs/0926_object_reader.md +93 -0
  114. data/core/src/docs/rfcs/0977_refactor_error.md +151 -0
  115. data/core/src/docs/rfcs/1085_object_handler.md +73 -0
  116. data/core/src/docs/rfcs/1391_object_metadataer.md +110 -0
  117. data/core/src/docs/rfcs/1398_query_based_metadata.md +125 -0
  118. data/core/src/docs/rfcs/1420_object_writer.md +147 -0
  119. data/core/src/docs/rfcs/1477_remove_object_concept.md +159 -0
  120. data/core/src/docs/rfcs/1735_operation_extension.md +117 -0
  121. data/core/src/docs/rfcs/2083_writer_sink_api.md +106 -0
  122. data/core/src/docs/rfcs/2133_append_api.md +88 -0
  123. data/core/src/docs/rfcs/2299_chain_based_operator_api.md +99 -0
  124. data/core/src/docs/rfcs/2602_object_versioning.md +138 -0
  125. data/core/src/docs/rfcs/2758_merge_append_into_write.md +79 -0
  126. data/core/src/docs/rfcs/2774_lister_api.md +66 -0
  127. data/core/src/docs/rfcs/2779_list_with_metakey.md +143 -0
  128. data/core/src/docs/rfcs/2852_native_capability.md +58 -0
  129. data/core/src/docs/rfcs/2884_merge_range_read_into_read.md +80 -0
  130. data/core/src/docs/rfcs/3017_remove_write_copy_from.md +94 -0
  131. data/core/src/docs/rfcs/3197_config.md +237 -0
  132. data/core/src/docs/rfcs/3232_align_list_api.md +69 -0
  133. data/core/src/docs/rfcs/3243_list_prefix.md +128 -0
  134. data/core/src/docs/rfcs/3356_lazy_reader.md +111 -0
  135. data/core/src/docs/rfcs/3526_list_recursive.md +59 -0
  136. data/core/src/docs/rfcs/3574_concurrent_stat_in_list.md +80 -0
  137. data/core/src/docs/rfcs/3734_buffered_reader.md +64 -0
  138. data/core/src/docs/rfcs/3898_concurrent_writer.md +66 -0
  139. data/core/src/docs/rfcs/3911_deleter_api.md +165 -0
  140. data/core/src/docs/rfcs/4382_range_based_read.md +213 -0
  141. data/core/src/docs/rfcs/4638_executor.md +215 -0
  142. data/core/src/docs/rfcs/5314_remove_metakey.md +120 -0
  143. data/core/src/docs/rfcs/5444_operator_from_uri.md +162 -0
  144. data/core/src/docs/rfcs/5479_context.md +140 -0
  145. data/core/src/docs/rfcs/5485_conditional_reader.md +112 -0
  146. data/core/src/docs/rfcs/5495_list_with_deleted.md +81 -0
  147. data/core/src/docs/rfcs/5556_write_returns_metadata.md +121 -0
  148. data/core/src/docs/rfcs/5871_read_returns_metadata.md +112 -0
  149. data/core/src/docs/rfcs/6189_remove_native_blocking.md +106 -0
  150. data/core/src/docs/rfcs/6209_glob_support.md +132 -0
  151. data/core/src/docs/rfcs/6213_options_api.md +142 -0
  152. data/core/src/docs/rfcs/README.md +62 -0
  153. data/core/src/docs/rfcs/mod.rs +278 -0
  154. data/core/src/docs/upgrade.md +1556 -0
  155. data/core/src/layers/async_backtrace.rs +174 -0
  156. data/core/src/layers/await_tree.rs +202 -0
  157. data/core/src/layers/capability_check.rs +239 -0
  158. data/core/src/layers/chaos.rs +170 -0
  159. data/core/src/layers/complete.rs +385 -0
  160. data/core/src/layers/concurrent_limit.rs +322 -0
  161. data/core/src/layers/correctness_check.rs +440 -0
  162. data/core/src/layers/dtrace.rs +294 -0
  163. data/core/src/layers/error_context.rs +310 -0
  164. data/core/src/layers/fastmetrics.rs +525 -0
  165. data/core/src/layers/fastrace.rs +271 -0
  166. data/core/src/layers/http_client.rs +206 -0
  167. data/core/src/layers/immutable_index.rs +408 -0
  168. data/core/src/layers/logging.rs +842 -0
  169. data/core/src/layers/metrics.rs +182 -0
  170. data/core/src/layers/mime_guess.rs +199 -0
  171. data/core/src/layers/mod.rs +130 -0
  172. data/core/src/layers/observe/metrics.rs +936 -0
  173. data/core/src/layers/observe/mod.rs +93 -0
  174. data/core/src/layers/otelmetrics.rs +496 -0
  175. data/core/src/layers/oteltrace.rs +203 -0
  176. data/core/src/layers/prometheus.rs +686 -0
  177. data/core/src/layers/prometheus_client.rs +519 -0
  178. data/core/src/layers/retry.rs +933 -0
  179. data/core/src/layers/throttle.rs +204 -0
  180. data/core/src/layers/timeout.rs +513 -0
  181. data/core/src/layers/tracing.rs +349 -0
  182. data/core/src/layers/type_eraser.rs +91 -0
  183. data/core/src/lib.rs +204 -0
  184. data/core/src/raw/accessor.rs +856 -0
  185. data/core/src/raw/adapters/kv/api.rs +164 -0
  186. data/core/src/raw/adapters/kv/backend.rs +253 -0
  187. data/core/src/raw/adapters/kv/mod.rs +31 -0
  188. data/core/src/raw/adapters/mod.rs +50 -0
  189. data/core/src/raw/adapters/typed_kv/api.rs +171 -0
  190. data/core/src/raw/adapters/typed_kv/backend.rs +279 -0
  191. data/core/src/raw/adapters/typed_kv/mod.rs +29 -0
  192. data/core/src/raw/atomic_util.rs +57 -0
  193. data/core/src/raw/azure.rs +570 -0
  194. data/core/src/raw/chrono_util.rs +109 -0
  195. data/core/src/raw/enum_utils.rs +201 -0
  196. data/core/src/raw/futures_util.rs +470 -0
  197. data/core/src/raw/http_util/body.rs +144 -0
  198. data/core/src/raw/http_util/bytes_content_range.rs +239 -0
  199. data/core/src/raw/http_util/bytes_range.rs +260 -0
  200. data/core/src/raw/http_util/client.rs +276 -0
  201. data/core/src/raw/http_util/error.rs +68 -0
  202. data/core/src/raw/http_util/header.rs +356 -0
  203. data/core/src/raw/http_util/mod.rs +78 -0
  204. data/core/src/raw/http_util/multipart.rs +1180 -0
  205. data/core/src/raw/http_util/uri.rs +190 -0
  206. data/core/src/raw/layer.rs +295 -0
  207. data/core/src/raw/mod.rs +101 -0
  208. data/core/src/raw/oio/buf/flex_buf.rs +118 -0
  209. data/core/src/raw/oio/buf/mod.rs +25 -0
  210. data/core/src/raw/oio/buf/pooled_buf.rs +126 -0
  211. data/core/src/raw/oio/buf/queue_buf.rs +117 -0
  212. data/core/src/raw/oio/delete/api.rs +102 -0
  213. data/core/src/raw/oio/delete/batch_delete.rs +127 -0
  214. data/core/src/raw/oio/delete/mod.rs +30 -0
  215. data/core/src/raw/oio/delete/one_shot_delete.rs +79 -0
  216. data/core/src/raw/oio/entry.rs +89 -0
  217. data/core/src/raw/oio/list/api.rs +69 -0
  218. data/core/src/raw/oio/list/flat_list.rs +137 -0
  219. data/core/src/raw/oio/list/hierarchy_list.rs +135 -0
  220. data/core/src/raw/oio/list/mod.rs +35 -0
  221. data/core/src/raw/oio/list/page_list.rs +105 -0
  222. data/core/src/raw/oio/list/prefix_list.rs +64 -0
  223. data/core/src/raw/oio/mod.rs +40 -0
  224. data/core/src/raw/oio/read/api.rs +119 -0
  225. data/core/src/raw/oio/read/mod.rs +21 -0
  226. data/core/src/raw/oio/write/api.rs +103 -0
  227. data/core/src/raw/oio/write/append_write.rs +111 -0
  228. data/core/src/raw/oio/write/block_write.rs +405 -0
  229. data/core/src/raw/oio/write/mod.rs +42 -0
  230. data/core/src/raw/oio/write/multipart_write.rs +518 -0
  231. data/core/src/raw/oio/write/one_shot_write.rs +77 -0
  232. data/core/src/raw/oio/write/position_write.rs +284 -0
  233. data/core/src/raw/operation.rs +88 -0
  234. data/core/src/raw/ops.rs +917 -0
  235. data/core/src/raw/path.rs +451 -0
  236. data/core/src/raw/path_cache.rs +244 -0
  237. data/core/src/raw/rps.rs +249 -0
  238. data/core/src/raw/serde_util.rs +423 -0
  239. data/core/src/raw/std_io_util.rs +65 -0
  240. data/core/src/raw/tests/mod.rs +30 -0
  241. data/core/src/raw/tests/read.rs +116 -0
  242. data/core/src/raw/tests/utils.rs +80 -0
  243. data/core/src/raw/tests/write.rs +79 -0
  244. data/core/src/raw/tokio_util.rs +24 -0
  245. data/core/src/raw/version.rs +19 -0
  246. data/core/src/services/aliyun_drive/backend.rs +421 -0
  247. data/core/src/services/aliyun_drive/config.rs +72 -0
  248. data/core/src/services/aliyun_drive/core.rs +651 -0
  249. data/core/src/services/aliyun_drive/delete.rs +51 -0
  250. data/core/src/services/aliyun_drive/docs.md +61 -0
  251. data/core/src/services/aliyun_drive/error.rs +56 -0
  252. data/core/src/services/aliyun_drive/lister.rs +134 -0
  253. data/core/src/services/aliyun_drive/mod.rs +39 -0
  254. data/core/src/services/aliyun_drive/writer.rs +114 -0
  255. data/core/src/services/alluxio/backend.rs +257 -0
  256. data/core/src/services/alluxio/config.rs +50 -0
  257. data/core/src/services/alluxio/core.rs +367 -0
  258. data/core/src/services/alluxio/delete.rs +38 -0
  259. data/core/src/services/alluxio/docs.md +45 -0
  260. data/core/src/services/alluxio/error.rs +99 -0
  261. data/core/src/services/alluxio/lister.rs +73 -0
  262. data/core/src/services/alluxio/mod.rs +39 -0
  263. data/core/src/services/alluxio/writer.rs +74 -0
  264. data/core/src/services/azblob/backend.rs +594 -0
  265. data/core/src/services/azblob/config.rs +220 -0
  266. data/core/src/services/azblob/core.rs +937 -0
  267. data/core/src/services/azblob/delete.rs +108 -0
  268. data/core/src/services/azblob/docs.md +77 -0
  269. data/core/src/services/azblob/error.rs +164 -0
  270. data/core/src/services/azblob/lister.rs +107 -0
  271. data/core/src/services/azblob/mod.rs +38 -0
  272. data/core/src/services/azblob/writer.rs +177 -0
  273. data/core/src/services/azdls/backend.rs +435 -0
  274. data/core/src/services/azdls/config.rs +89 -0
  275. data/core/src/services/azdls/core.rs +388 -0
  276. data/core/src/services/azdls/delete.rs +48 -0
  277. data/core/src/services/azdls/docs.md +73 -0
  278. data/core/src/services/azdls/error.rs +107 -0
  279. data/core/src/services/azdls/lister.rs +165 -0
  280. data/core/src/services/azdls/mod.rs +38 -0
  281. data/core/src/services/azdls/writer.rs +129 -0
  282. data/core/src/services/azfile/backend.rs +373 -0
  283. data/core/src/services/azfile/config.rs +61 -0
  284. data/core/src/services/azfile/core.rs +435 -0
  285. data/core/src/services/azfile/delete.rs +51 -0
  286. data/core/src/services/azfile/docs.md +65 -0
  287. data/core/src/services/azfile/error.rs +108 -0
  288. data/core/src/services/azfile/lister.rs +217 -0
  289. data/core/src/services/azfile/mod.rs +39 -0
  290. data/core/src/services/azfile/writer.rs +92 -0
  291. data/core/src/services/b2/backend.rs +434 -0
  292. data/core/src/services/b2/config.rs +64 -0
  293. data/core/src/services/b2/core.rs +742 -0
  294. data/core/src/services/b2/delete.rs +56 -0
  295. data/core/src/services/b2/docs.md +54 -0
  296. data/core/src/services/b2/error.rs +132 -0
  297. data/core/src/services/b2/lister.rs +110 -0
  298. data/core/src/services/b2/mod.rs +39 -0
  299. data/core/src/services/b2/writer.rs +189 -0
  300. data/core/src/services/cacache/backend.rs +160 -0
  301. data/core/src/services/cacache/config.rs +28 -0
  302. data/core/src/services/cacache/core.rs +96 -0
  303. data/core/src/services/cacache/delete.rs +39 -0
  304. data/core/src/services/cacache/docs.md +38 -0
  305. data/core/src/services/cacache/mod.rs +34 -0
  306. data/core/src/services/cacache/writer.rs +61 -0
  307. data/core/src/services/cloudflare_kv/backend.rs +513 -0
  308. data/core/src/services/cloudflare_kv/config.rs +55 -0
  309. data/core/src/services/cloudflare_kv/core.rs +168 -0
  310. data/core/src/services/cloudflare_kv/delete.rs +119 -0
  311. data/core/src/services/cloudflare_kv/docs.md +21 -0
  312. data/core/src/services/cloudflare_kv/error.rs +79 -0
  313. data/core/src/services/cloudflare_kv/lister.rs +170 -0
  314. data/core/src/services/cloudflare_kv/mod.rs +39 -0
  315. data/core/src/services/cloudflare_kv/model.rs +76 -0
  316. data/core/src/services/cloudflare_kv/writer.rs +68 -0
  317. data/core/src/services/compfs/backend.rs +290 -0
  318. data/core/src/services/compfs/config.rs +30 -0
  319. data/core/src/services/compfs/core.rs +159 -0
  320. data/core/src/services/compfs/delete.rs +53 -0
  321. data/core/src/services/compfs/lister.rs +98 -0
  322. data/core/src/services/compfs/mod.rs +38 -0
  323. data/core/src/services/compfs/reader.rs +79 -0
  324. data/core/src/services/compfs/writer.rs +90 -0
  325. data/core/src/services/cos/backend.rs +442 -0
  326. data/core/src/services/cos/config.rs +54 -0
  327. data/core/src/services/cos/core.rs +761 -0
  328. data/core/src/services/cos/delete.rs +48 -0
  329. data/core/src/services/cos/docs.md +55 -0
  330. data/core/src/services/cos/error.rs +105 -0
  331. data/core/src/services/cos/lister.rs +237 -0
  332. data/core/src/services/cos/mod.rs +39 -0
  333. data/core/src/services/cos/writer.rs +234 -0
  334. data/core/src/services/d1/backend.rs +330 -0
  335. data/core/src/services/d1/config.rs +55 -0
  336. data/core/src/services/d1/docs.md +48 -0
  337. data/core/src/services/d1/error.rs +79 -0
  338. data/core/src/services/d1/mod.rs +29 -0
  339. data/core/src/services/d1/model.rs +125 -0
  340. data/core/src/services/dashmap/backend.rs +203 -0
  341. data/core/src/services/dashmap/config.rs +37 -0
  342. data/core/src/services/dashmap/core.rs +61 -0
  343. data/core/src/services/dashmap/delete.rs +40 -0
  344. data/core/src/services/dashmap/docs.md +38 -0
  345. data/core/src/services/dashmap/lister.rs +63 -0
  346. data/core/src/services/dashmap/mod.rs +36 -0
  347. data/core/src/services/dashmap/writer.rs +87 -0
  348. data/core/src/services/dbfs/backend.rs +258 -0
  349. data/core/src/services/dbfs/config.rs +48 -0
  350. data/core/src/services/dbfs/core.rs +191 -0
  351. data/core/src/services/dbfs/delete.rs +49 -0
  352. data/core/src/services/dbfs/docs.md +57 -0
  353. data/core/src/services/dbfs/error.rs +74 -0
  354. data/core/src/services/dbfs/lister.rs +96 -0
  355. data/core/src/services/dbfs/mod.rs +38 -0
  356. data/core/src/services/dbfs/writer.rs +64 -0
  357. data/core/src/services/dropbox/backend.rs +187 -0
  358. data/core/src/services/dropbox/builder.rs +222 -0
  359. data/core/src/services/dropbox/config.rs +47 -0
  360. data/core/src/services/dropbox/core.rs +496 -0
  361. data/core/src/services/dropbox/delete.rs +54 -0
  362. data/core/src/services/dropbox/docs.md +64 -0
  363. data/core/src/services/dropbox/error.rs +85 -0
  364. data/core/src/services/dropbox/lister.rs +117 -0
  365. data/core/src/services/dropbox/mod.rs +40 -0
  366. data/core/src/services/dropbox/writer.rs +51 -0
  367. data/core/src/services/etcd/backend.rs +345 -0
  368. data/core/src/services/etcd/config.rs +86 -0
  369. data/core/src/services/etcd/core.rs +143 -0
  370. data/core/src/services/etcd/deleter.rs +41 -0
  371. data/core/src/services/etcd/docs.md +45 -0
  372. data/core/src/services/etcd/error.rs +26 -0
  373. data/core/src/services/etcd/lister.rs +79 -0
  374. data/core/src/services/etcd/mod.rs +36 -0
  375. data/core/src/services/etcd/writer.rs +61 -0
  376. data/core/src/services/foundationdb/backend.rs +171 -0
  377. data/core/src/services/foundationdb/config.rs +45 -0
  378. data/core/src/services/foundationdb/docs.md +42 -0
  379. data/core/src/services/foundationdb/mod.rs +24 -0
  380. data/core/src/services/fs/backend.rs +299 -0
  381. data/core/src/services/fs/config.rs +33 -0
  382. data/core/src/services/fs/core.rs +227 -0
  383. data/core/src/services/fs/delete.rs +53 -0
  384. data/core/src/services/fs/docs.md +49 -0
  385. data/core/src/services/fs/error.rs +31 -0
  386. data/core/src/services/fs/lister.rs +81 -0
  387. data/core/src/services/fs/mod.rs +40 -0
  388. data/core/src/services/fs/reader.rs +83 -0
  389. data/core/src/services/fs/writer.rs +212 -0
  390. data/core/src/services/ftp/backend.rs +388 -0
  391. data/core/src/services/ftp/config.rs +46 -0
  392. data/core/src/services/ftp/core.rs +136 -0
  393. data/core/src/services/ftp/delete.rs +62 -0
  394. data/core/src/services/ftp/docs.md +42 -0
  395. data/core/src/services/ftp/err.rs +47 -0
  396. data/core/src/services/ftp/lister.rs +72 -0
  397. data/core/src/services/ftp/mod.rs +41 -0
  398. data/core/src/services/ftp/reader.rs +84 -0
  399. data/core/src/services/ftp/writer.rs +122 -0
  400. data/core/src/services/gcs/backend.rs +499 -0
  401. data/core/src/services/gcs/config.rs +168 -0
  402. data/core/src/services/gcs/core.rs +1079 -0
  403. data/core/src/services/gcs/delete.rs +98 -0
  404. data/core/src/services/gcs/docs.md +76 -0
  405. data/core/src/services/gcs/error.rs +122 -0
  406. data/core/src/services/gcs/lister.rs +136 -0
  407. data/core/src/services/gcs/mod.rs +40 -0
  408. data/core/src/services/gcs/uri.rs +75 -0
  409. data/core/src/services/gcs/writer.rs +163 -0
  410. data/core/src/services/gdrive/backend.rs +176 -0
  411. data/core/src/services/gdrive/builder.rs +228 -0
  412. data/core/src/services/gdrive/config.rs +47 -0
  413. data/core/src/services/gdrive/core.rs +499 -0
  414. data/core/src/services/gdrive/delete.rs +57 -0
  415. data/core/src/services/gdrive/docs.md +65 -0
  416. data/core/src/services/gdrive/error.rs +80 -0
  417. data/core/src/services/gdrive/lister.rs +110 -0
  418. data/core/src/services/gdrive/mod.rs +40 -0
  419. data/core/src/services/gdrive/writer.rs +77 -0
  420. data/core/src/services/ghac/backend.rs +285 -0
  421. data/core/src/services/ghac/config.rs +36 -0
  422. data/core/src/services/ghac/core.rs +459 -0
  423. data/core/src/services/ghac/docs.md +84 -0
  424. data/core/src/services/ghac/error.rs +52 -0
  425. data/core/src/services/ghac/mod.rs +35 -0
  426. data/core/src/services/ghac/writer.rs +201 -0
  427. data/core/src/services/github/backend.rs +285 -0
  428. data/core/src/services/github/config.rs +59 -0
  429. data/core/src/services/github/core.rs +351 -0
  430. data/core/src/services/github/delete.rs +41 -0
  431. data/core/src/services/github/docs.md +52 -0
  432. data/core/src/services/github/error.rs +101 -0
  433. data/core/src/services/github/lister.rs +112 -0
  434. data/core/src/services/github/mod.rs +38 -0
  435. data/core/src/services/github/writer.rs +51 -0
  436. data/core/src/services/gridfs/backend.rs +166 -0
  437. data/core/src/services/gridfs/config.rs +50 -0
  438. data/core/src/services/gridfs/core.rs +154 -0
  439. data/core/src/services/gridfs/docs.md +46 -0
  440. data/core/src/services/gridfs/mod.rs +26 -0
  441. data/core/src/services/hdfs/backend.rs +413 -0
  442. data/core/src/services/hdfs/config.rs +59 -0
  443. data/core/src/services/hdfs/delete.rs +62 -0
  444. data/core/src/services/hdfs/docs.md +140 -0
  445. data/core/src/services/hdfs/lister.rs +70 -0
  446. data/core/src/services/hdfs/mod.rs +36 -0
  447. data/core/src/services/hdfs/reader.rs +79 -0
  448. data/core/src/services/hdfs/writer.rs +104 -0
  449. data/core/src/services/hdfs_native/backend.rs +340 -0
  450. data/core/src/services/hdfs_native/config.rs +45 -0
  451. data/core/src/services/hdfs_native/delete.rs +47 -0
  452. data/core/src/services/hdfs_native/docs.md +35 -0
  453. data/core/src/services/hdfs_native/error.rs +59 -0
  454. data/core/src/services/hdfs_native/lister.rs +85 -0
  455. data/core/src/services/hdfs_native/mod.rs +39 -0
  456. data/core/src/services/hdfs_native/reader.rs +62 -0
  457. data/core/src/services/hdfs_native/writer.rs +61 -0
  458. data/core/src/services/http/backend.rs +291 -0
  459. data/core/src/services/http/config.rs +49 -0
  460. data/core/src/services/http/core.rs +125 -0
  461. data/core/src/services/http/docs.md +45 -0
  462. data/core/src/services/http/error.rs +53 -0
  463. data/core/src/services/http/mod.rs +32 -0
  464. data/core/src/services/huggingface/backend.rs +289 -0
  465. data/core/src/services/huggingface/config.rs +75 -0
  466. data/core/src/services/huggingface/core.rs +406 -0
  467. data/core/src/services/huggingface/docs.md +61 -0
  468. data/core/src/services/huggingface/error.rs +93 -0
  469. data/core/src/services/huggingface/lister.rs +91 -0
  470. data/core/src/services/huggingface/mod.rs +34 -0
  471. data/core/src/services/ipfs/backend.rs +257 -0
  472. data/core/src/services/ipfs/config.rs +32 -0
  473. data/core/src/services/ipfs/core.rs +239 -0
  474. data/core/src/services/ipfs/docs.md +45 -0
  475. data/core/src/services/ipfs/error.rs +52 -0
  476. data/core/src/services/ipfs/ipld.rs +162 -0
  477. data/core/src/services/ipfs/mod.rs +34 -0
  478. data/core/src/services/ipmfs/backend.rs +147 -0
  479. data/core/src/services/ipmfs/builder.rs +166 -0
  480. data/core/src/services/ipmfs/config.rs +32 -0
  481. data/core/src/services/ipmfs/core.rs +142 -0
  482. data/core/src/services/ipmfs/delete.rs +48 -0
  483. data/core/src/services/ipmfs/docs.md +14 -0
  484. data/core/src/services/ipmfs/error.rs +83 -0
  485. data/core/src/services/ipmfs/lister.rs +135 -0
  486. data/core/src/services/ipmfs/mod.rs +40 -0
  487. data/core/src/services/ipmfs/writer.rs +49 -0
  488. data/core/src/services/koofr/backend.rs +361 -0
  489. data/core/src/services/koofr/config.rs +50 -0
  490. data/core/src/services/koofr/core.rs +458 -0
  491. data/core/src/services/koofr/delete.rs +50 -0
  492. data/core/src/services/koofr/docs.md +51 -0
  493. data/core/src/services/koofr/error.rs +72 -0
  494. data/core/src/services/koofr/lister.rs +88 -0
  495. data/core/src/services/koofr/mod.rs +38 -0
  496. data/core/src/services/koofr/writer.rs +53 -0
  497. data/core/src/services/lakefs/backend.rs +309 -0
  498. data/core/src/services/lakefs/config.rs +81 -0
  499. data/core/src/services/lakefs/core.rs +261 -0
  500. data/core/src/services/lakefs/delete.rs +54 -0
  501. data/core/src/services/lakefs/docs.md +62 -0
  502. data/core/src/services/lakefs/error.rs +93 -0
  503. data/core/src/services/lakefs/lister.rs +120 -0
  504. data/core/src/services/lakefs/mod.rs +38 -0
  505. data/core/src/services/lakefs/writer.rs +50 -0
  506. data/core/src/services/memcached/backend.rs +284 -0
  507. data/core/src/services/memcached/binary.rs +289 -0
  508. data/core/src/services/memcached/config.rs +43 -0
  509. data/core/src/services/memcached/docs.md +47 -0
  510. data/core/src/services/memcached/mod.rs +27 -0
  511. data/core/src/services/memory/backend.rs +205 -0
  512. data/core/src/services/memory/config.rs +30 -0
  513. data/core/src/services/memory/core.rs +80 -0
  514. data/core/src/services/memory/delete.rs +42 -0
  515. data/core/src/services/memory/docs.md +36 -0
  516. data/core/src/services/memory/lister.rs +56 -0
  517. data/core/src/services/memory/mod.rs +36 -0
  518. data/core/src/services/memory/writer.rs +85 -0
  519. data/core/src/services/mini_moka/backend.rs +260 -0
  520. data/core/src/services/mini_moka/config.rs +56 -0
  521. data/core/src/services/mini_moka/core.rs +52 -0
  522. data/core/src/services/mini_moka/delete.rs +42 -0
  523. data/core/src/services/mini_moka/docs.md +19 -0
  524. data/core/src/services/mini_moka/lister.rs +68 -0
  525. data/core/src/services/mini_moka/mod.rs +36 -0
  526. data/core/src/services/mini_moka/writer.rs +84 -0
  527. data/core/src/services/mod.rs +206 -0
  528. data/core/src/services/moka/backend.rs +326 -0
  529. data/core/src/services/moka/config.rs +59 -0
  530. data/core/src/services/moka/core.rs +62 -0
  531. data/core/src/services/moka/delete.rs +42 -0
  532. data/core/src/services/moka/docs.md +42 -0
  533. data/core/src/services/moka/lister.rs +65 -0
  534. data/core/src/services/moka/mod.rs +41 -0
  535. data/core/src/services/moka/writer.rs +83 -0
  536. data/core/src/services/mongodb/backend.rs +291 -0
  537. data/core/src/services/mongodb/config.rs +54 -0
  538. data/core/src/services/mongodb/docs.md +49 -0
  539. data/core/src/services/mongodb/mod.rs +24 -0
  540. data/core/src/services/monoiofs/backend.rs +238 -0
  541. data/core/src/services/monoiofs/config.rs +34 -0
  542. data/core/src/services/monoiofs/core.rs +313 -0
  543. data/core/src/services/monoiofs/delete.rs +64 -0
  544. data/core/src/services/monoiofs/docs.md +46 -0
  545. data/core/src/services/monoiofs/mod.rs +36 -0
  546. data/core/src/services/monoiofs/reader.rs +147 -0
  547. data/core/src/services/monoiofs/writer.rs +189 -0
  548. data/core/src/services/mysql/backend.rs +256 -0
  549. data/core/src/services/mysql/config.rs +66 -0
  550. data/core/src/services/mysql/docs.md +47 -0
  551. data/core/src/services/mysql/mod.rs +24 -0
  552. data/core/src/services/obs/backend.rs +442 -0
  553. data/core/src/services/obs/config.rs +53 -0
  554. data/core/src/services/obs/core.rs +608 -0
  555. data/core/src/services/obs/delete.rs +48 -0
  556. data/core/src/services/obs/docs.md +54 -0
  557. data/core/src/services/obs/error.rs +106 -0
  558. data/core/src/services/obs/lister.rs +101 -0
  559. data/core/src/services/obs/mod.rs +38 -0
  560. data/core/src/services/obs/writer.rs +235 -0
  561. data/core/src/services/onedrive/backend.rs +127 -0
  562. data/core/src/services/onedrive/builder.rs +236 -0
  563. data/core/src/services/onedrive/config.rs +49 -0
  564. data/core/src/services/onedrive/core.rs +691 -0
  565. data/core/src/services/onedrive/delete.rs +47 -0
  566. data/core/src/services/onedrive/docs.md +115 -0
  567. data/core/src/services/onedrive/error.rs +61 -0
  568. data/core/src/services/onedrive/graph_model.rs +425 -0
  569. data/core/src/services/onedrive/lister.rs +150 -0
  570. data/core/src/services/onedrive/mod.rs +42 -0
  571. data/core/src/services/onedrive/writer.rs +168 -0
  572. data/core/src/services/opfs/backend.rs +50 -0
  573. data/core/src/services/opfs/config.rs +25 -0
  574. data/core/src/services/opfs/core.rs +74 -0
  575. data/core/src/services/opfs/docs.md +18 -0
  576. data/core/src/services/opfs/error.rs +27 -0
  577. data/core/src/services/opfs/mod.rs +30 -0
  578. data/core/src/services/opfs/utils.rs +70 -0
  579. data/core/src/services/oss/backend.rs +734 -0
  580. data/core/src/services/oss/config.rs +113 -0
  581. data/core/src/services/oss/core.rs +1088 -0
  582. data/core/src/services/oss/delete.rs +109 -0
  583. data/core/src/services/oss/docs.md +74 -0
  584. data/core/src/services/oss/error.rs +109 -0
  585. data/core/src/services/oss/lister.rs +256 -0
  586. data/core/src/services/oss/mod.rs +38 -0
  587. data/core/src/services/oss/writer.rs +228 -0
  588. data/core/src/services/pcloud/backend.rs +358 -0
  589. data/core/src/services/pcloud/config.rs +51 -0
  590. data/core/src/services/pcloud/core.rs +461 -0
  591. data/core/src/services/pcloud/delete.rs +66 -0
  592. data/core/src/services/pcloud/docs.md +51 -0
  593. data/core/src/services/pcloud/error.rs +88 -0
  594. data/core/src/services/pcloud/lister.rs +95 -0
  595. data/core/src/services/pcloud/mod.rs +38 -0
  596. data/core/src/services/pcloud/writer.rs +66 -0
  597. data/core/src/services/persy/backend.rs +226 -0
  598. data/core/src/services/persy/config.rs +32 -0
  599. data/core/src/services/persy/docs.md +43 -0
  600. data/core/src/services/persy/mod.rs +24 -0
  601. data/core/src/services/postgresql/backend.rs +258 -0
  602. data/core/src/services/postgresql/config.rs +66 -0
  603. data/core/src/services/postgresql/docs.md +47 -0
  604. data/core/src/services/postgresql/mod.rs +24 -0
  605. data/core/src/services/redb/backend.rs +280 -0
  606. data/core/src/services/redb/config.rs +34 -0
  607. data/core/src/services/redb/docs.md +41 -0
  608. data/core/src/services/redb/mod.rs +24 -0
  609. data/core/src/services/redis/backend.rs +442 -0
  610. data/core/src/services/redis/config.rs +79 -0
  611. data/core/src/services/redis/core.rs +209 -0
  612. data/core/src/services/redis/delete.rs +40 -0
  613. data/core/src/services/redis/docs.md +43 -0
  614. data/core/src/services/redis/mod.rs +34 -0
  615. data/core/src/services/redis/writer.rs +57 -0
  616. data/core/src/services/rocksdb/backend.rs +159 -0
  617. data/core/src/services/rocksdb/config.rs +34 -0
  618. data/core/src/services/rocksdb/docs.md +54 -0
  619. data/core/src/services/rocksdb/mod.rs +24 -0
  620. data/core/src/services/s3/backend.rs +1293 -0
  621. data/core/src/services/s3/compatible_services.md +126 -0
  622. data/core/src/services/s3/config.rs +327 -0
  623. data/core/src/services/s3/core.rs +1741 -0
  624. data/core/src/services/s3/delete.rs +109 -0
  625. data/core/src/services/s3/docs.md +244 -0
  626. data/core/src/services/s3/error.rs +171 -0
  627. data/core/src/services/s3/lister.rs +405 -0
  628. data/core/src/services/s3/mod.rs +38 -0
  629. data/core/src/services/s3/writer.rs +262 -0
  630. data/core/src/services/seafile/backend.rs +297 -0
  631. data/core/src/services/seafile/config.rs +56 -0
  632. data/core/src/services/seafile/core.rs +475 -0
  633. data/core/src/services/seafile/delete.rs +40 -0
  634. data/core/src/services/seafile/docs.md +54 -0
  635. data/core/src/services/seafile/error.rs +86 -0
  636. data/core/src/services/seafile/lister.rs +83 -0
  637. data/core/src/services/seafile/mod.rs +38 -0
  638. data/core/src/services/seafile/writer.rs +55 -0
  639. data/core/src/services/sftp/backend.rs +397 -0
  640. data/core/src/services/sftp/config.rs +50 -0
  641. data/core/src/services/sftp/core.rs +154 -0
  642. data/core/src/services/sftp/delete.rs +55 -0
  643. data/core/src/services/sftp/docs.md +49 -0
  644. data/core/src/services/sftp/error.rs +57 -0
  645. data/core/src/services/sftp/lister.rs +88 -0
  646. data/core/src/services/sftp/mod.rs +42 -0
  647. data/core/src/services/sftp/reader.rs +78 -0
  648. data/core/src/services/sftp/utils.rs +51 -0
  649. data/core/src/services/sftp/writer.rs +67 -0
  650. data/core/src/services/sled/backend.rs +194 -0
  651. data/core/src/services/sled/config.rs +45 -0
  652. data/core/src/services/sled/docs.md +39 -0
  653. data/core/src/services/sled/mod.rs +24 -0
  654. data/core/src/services/sqlite/backend.rs +326 -0
  655. data/core/src/services/sqlite/config.rs +70 -0
  656. data/core/src/services/sqlite/docs.md +46 -0
  657. data/core/src/services/sqlite/mod.rs +24 -0
  658. data/core/src/services/surrealdb/backend.rs +365 -0
  659. data/core/src/services/surrealdb/config.rs +64 -0
  660. data/core/src/services/surrealdb/docs.md +54 -0
  661. data/core/src/services/surrealdb/mod.rs +24 -0
  662. data/core/src/services/swift/backend.rs +275 -0
  663. data/core/src/services/swift/compatible_services.md +53 -0
  664. data/core/src/services/swift/config.rs +53 -0
  665. data/core/src/services/swift/core.rs +310 -0
  666. data/core/src/services/swift/delete.rs +49 -0
  667. data/core/src/services/swift/docs.md +52 -0
  668. data/core/src/services/swift/error.rs +90 -0
  669. data/core/src/services/swift/lister.rs +119 -0
  670. data/core/src/services/swift/mod.rs +38 -0
  671. data/core/src/services/swift/writer.rs +53 -0
  672. data/core/src/services/tikv/backend.rs +237 -0
  673. data/core/src/services/tikv/config.rs +52 -0
  674. data/core/src/services/tikv/docs.md +43 -0
  675. data/core/src/services/tikv/mod.rs +24 -0
  676. data/core/src/services/upyun/backend.rs +317 -0
  677. data/core/src/services/upyun/config.rs +51 -0
  678. data/core/src/services/upyun/core.rs +521 -0
  679. data/core/src/services/upyun/delete.rs +50 -0
  680. data/core/src/services/upyun/docs.md +51 -0
  681. data/core/src/services/upyun/error.rs +97 -0
  682. data/core/src/services/upyun/lister.rs +101 -0
  683. data/core/src/services/upyun/mod.rs +38 -0
  684. data/core/src/services/upyun/writer.rs +127 -0
  685. data/core/src/services/vercel_artifacts/backend.rs +99 -0
  686. data/core/src/services/vercel_artifacts/builder.rs +117 -0
  687. data/core/src/services/vercel_artifacts/config.rs +39 -0
  688. data/core/src/services/vercel_artifacts/core.rs +112 -0
  689. data/core/src/services/vercel_artifacts/docs.md +40 -0
  690. data/core/src/services/vercel_artifacts/error.rs +50 -0
  691. data/core/src/services/vercel_artifacts/mod.rs +36 -0
  692. data/core/src/services/vercel_artifacts/writer.rs +58 -0
  693. data/core/src/services/vercel_blob/backend.rs +251 -0
  694. data/core/src/services/vercel_blob/config.rs +45 -0
  695. data/core/src/services/vercel_blob/core.rs +449 -0
  696. data/core/src/services/vercel_blob/delete.rs +38 -0
  697. data/core/src/services/vercel_blob/docs.md +45 -0
  698. data/core/src/services/vercel_blob/error.rs +110 -0
  699. data/core/src/services/vercel_blob/lister.rs +69 -0
  700. data/core/src/services/vercel_blob/mod.rs +38 -0
  701. data/core/src/services/vercel_blob/writer.rs +143 -0
  702. data/core/src/services/webdav/backend.rs +318 -0
  703. data/core/src/services/webdav/config.rs +53 -0
  704. data/core/src/services/webdav/core.rs +859 -0
  705. data/core/src/services/webdav/delete.rs +47 -0
  706. data/core/src/services/webdav/docs.md +49 -0
  707. data/core/src/services/webdav/error.rs +53 -0
  708. data/core/src/services/webdav/lister.rs +106 -0
  709. data/core/src/services/webdav/mod.rs +38 -0
  710. data/core/src/services/webdav/writer.rs +56 -0
  711. data/core/src/services/webhdfs/backend.rs +376 -0
  712. data/core/src/services/webhdfs/config.rs +52 -0
  713. data/core/src/services/webhdfs/core.rs +398 -0
  714. data/core/src/services/webhdfs/delete.rs +46 -0
  715. data/core/src/services/webhdfs/docs.md +90 -0
  716. data/core/src/services/webhdfs/error.rs +126 -0
  717. data/core/src/services/webhdfs/lister.rs +130 -0
  718. data/core/src/services/webhdfs/message.rs +249 -0
  719. data/core/src/services/webhdfs/mod.rs +41 -0
  720. data/core/src/services/webhdfs/writer.rs +177 -0
  721. data/core/src/services/yandex_disk/backend.rs +267 -0
  722. data/core/src/services/yandex_disk/config.rs +45 -0
  723. data/core/src/services/yandex_disk/core.rs +340 -0
  724. data/core/src/services/yandex_disk/delete.rs +54 -0
  725. data/core/src/services/yandex_disk/docs.md +45 -0
  726. data/core/src/services/yandex_disk/error.rs +104 -0
  727. data/core/src/services/yandex_disk/lister.rs +113 -0
  728. data/core/src/services/yandex_disk/mod.rs +38 -0
  729. data/core/src/services/yandex_disk/writer.rs +52 -0
  730. data/core/src/types/buffer.rs +991 -0
  731. data/core/src/types/builder.rs +152 -0
  732. data/core/src/types/capability.rs +209 -0
  733. data/core/src/types/context/mod.rs +22 -0
  734. data/core/src/types/context/read.rs +231 -0
  735. data/core/src/types/context/write.rs +441 -0
  736. data/core/src/types/delete/deleter.rs +220 -0
  737. data/core/src/types/delete/futures_delete_sink.rs +176 -0
  738. data/core/src/types/delete/input.rs +97 -0
  739. data/core/src/types/delete/mod.rs +26 -0
  740. data/core/src/types/entry.rs +69 -0
  741. data/core/src/types/error.rs +570 -0
  742. data/core/src/types/execute/api.rs +110 -0
  743. data/core/src/types/execute/executor.rs +96 -0
  744. data/core/src/types/execute/executors/mod.rs +27 -0
  745. data/core/src/types/execute/executors/tokio_executor.rs +60 -0
  746. data/core/src/types/execute/mod.rs +25 -0
  747. data/core/src/types/list.rs +137 -0
  748. data/core/src/types/metadata.rs +436 -0
  749. data/core/src/types/mod.rs +72 -0
  750. data/core/src/types/mode.rs +68 -0
  751. data/core/src/types/operator/builder.rs +535 -0
  752. data/core/src/types/operator/info.rs +63 -0
  753. data/core/src/types/operator/mod.rs +33 -0
  754. data/core/src/types/operator/operator.rs +2236 -0
  755. data/core/src/types/operator/operator_futures.rs +1430 -0
  756. data/core/src/types/operator/registry.rs +129 -0
  757. data/core/src/types/options.rs +548 -0
  758. data/core/src/types/read/buffer_stream.rs +273 -0
  759. data/core/src/types/read/futures_async_reader.rs +289 -0
  760. data/core/src/types/read/futures_bytes_stream.rs +157 -0
  761. data/core/src/types/read/mod.rs +29 -0
  762. data/core/src/types/read/reader.rs +604 -0
  763. data/core/src/types/scheme.rs +475 -0
  764. data/core/src/types/write/buffer_sink.rs +188 -0
  765. data/core/src/types/write/futures_async_writer.rs +136 -0
  766. data/core/src/types/write/futures_bytes_sink.rs +103 -0
  767. data/core/src/types/write/mod.rs +26 -0
  768. data/core/src/types/write/writer.rs +411 -0
  769. data/core/tests/behavior/README.md +77 -0
  770. data/core/tests/behavior/async_copy.rs +314 -0
  771. data/core/tests/behavior/async_create_dir.rs +53 -0
  772. data/core/tests/behavior/async_delete.rs +354 -0
  773. data/core/tests/behavior/async_list.rs +739 -0
  774. data/core/tests/behavior/async_presign.rs +175 -0
  775. data/core/tests/behavior/async_read.rs +871 -0
  776. data/core/tests/behavior/async_rename.rs +210 -0
  777. data/core/tests/behavior/async_stat.rs +628 -0
  778. data/core/tests/behavior/async_write.rs +819 -0
  779. data/core/tests/behavior/main.rs +78 -0
  780. data/core/tests/behavior/utils.rs +187 -0
  781. data/core/tests/data/normal_dir/.gitkeep +0 -0
  782. data/core/tests/data/normal_file.txt +1041 -0
  783. data/core/tests/data/special_dir !@#$%^&()_+-=;',/.gitkeep +0 -0
  784. data/core/tests/data/special_file !@#$%^&()_+-=;',.txt +1041 -0
  785. data/core/users.md +13 -0
  786. data/extconf.rb +24 -0
  787. data/lib/opendal.rb +25 -0
  788. data/lib/opendal_ruby/entry.rb +35 -0
  789. data/lib/opendal_ruby/io.rb +70 -0
  790. data/lib/opendal_ruby/metadata.rb +44 -0
  791. data/lib/opendal_ruby/operator.rb +29 -0
  792. data/lib/opendal_ruby/operator_info.rb +26 -0
  793. data/src/capability.rs +146 -0
  794. data/src/io.rs +464 -0
  795. data/src/lib.rs +63 -0
  796. data/src/lister.rs +141 -0
  797. data/src/metadata.rs +111 -0
  798. data/src/middlewares.rs +174 -0
  799. data/src/operator.rs +310 -0
  800. data/src/operator_info.rs +83 -0
  801. data/test/blocking_op_test.rb +112 -0
  802. data/test/capability_test.rb +42 -0
  803. data/test/io_test.rb +172 -0
  804. data/test/lister_test.rb +77 -0
  805. data/test/metadata_test.rb +78 -0
  806. data/test/middlewares_test.rb +46 -0
  807. data/test/operator_info_test.rb +35 -0
  808. data/test/test_helper.rb +36 -0
  809. metadata +857 -0
@@ -0,0 +1,871 @@
1
+ // Licensed to the Apache Software Foundation (ASF) under one
2
+ // or more contributor license agreements. See the NOTICE file
3
+ // distributed with this work for additional information
4
+ // regarding copyright ownership. The ASF licenses this file
5
+ // to you under the Apache License, Version 2.0 (the
6
+ // "License"); you may not use this file except in compliance
7
+ // with the License. You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing,
12
+ // software distributed under the License is distributed on an
13
+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ // KIND, either express or implied. See the License for the
15
+ // specific language governing permissions and limitations
16
+ // under the License.
17
+
18
+ use std::str::FromStr;
19
+ use std::time::Duration;
20
+
21
+ use futures::AsyncReadExt;
22
+ use futures::TryStreamExt;
23
+ use http::StatusCode;
24
+ use log::warn;
25
+ use reqwest::Url;
26
+ use sha2::Digest;
27
+ use sha2::Sha256;
28
+ use tokio::time::sleep;
29
+
30
+ use crate::*;
31
+
32
+ pub fn tests(op: &Operator, tests: &mut Vec<Trial>) {
33
+ let cap = op.info().full_capability();
34
+
35
+ if cap.read && cap.write {
36
+ tests.extend(async_trials!(
37
+ op,
38
+ test_read_full,
39
+ test_read_range,
40
+ test_reader,
41
+ test_reader_with_if_match,
42
+ test_reader_with_if_none_match,
43
+ test_reader_with_if_modified_since,
44
+ test_reader_with_if_unmodified_since,
45
+ test_read_not_exist,
46
+ test_read_with_if_match,
47
+ test_read_with_if_none_match,
48
+ test_read_with_if_modified_since,
49
+ test_read_with_if_unmodified_since,
50
+ test_read_with_dir_path,
51
+ test_read_with_special_chars,
52
+ test_read_with_override_cache_control,
53
+ test_read_with_override_content_disposition,
54
+ test_read_with_override_content_type,
55
+ test_read_with_version,
56
+ test_read_with_not_existing_version
57
+ ))
58
+ }
59
+
60
+ if cap.read && !cap.write {
61
+ tests.extend(async_trials!(
62
+ op,
63
+ test_read_only_read_full,
64
+ test_read_only_read_full_with_special_chars,
65
+ test_read_only_read_with_range,
66
+ test_read_only_read_not_exist,
67
+ test_read_only_read_with_dir_path,
68
+ test_read_only_read_with_if_match,
69
+ test_read_only_read_with_if_none_match,
70
+ test_reader_only_read_with_if_match,
71
+ test_reader_only_read_with_if_none_match
72
+ ))
73
+ }
74
+ }
75
+
76
+ /// Read full content should match.
77
+ pub async fn test_read_full(op: Operator) -> anyhow::Result<()> {
78
+ let (path, content, size) = TEST_FIXTURE.new_file(op.clone());
79
+
80
+ op.write(&path, content.clone())
81
+ .await
82
+ .expect("write must succeed");
83
+
84
+ let bs = op.read(&path).await?.to_bytes();
85
+ assert_eq!(size, bs.len(), "read size");
86
+ assert_eq!(
87
+ format!("{:x}", Sha256::digest(&bs)),
88
+ format!("{:x}", Sha256::digest(&content)),
89
+ "read content"
90
+ );
91
+
92
+ Ok(())
93
+ }
94
+
95
+ /// Read range content should match.
96
+ pub async fn test_read_range(op: Operator) -> anyhow::Result<()> {
97
+ let (path, content, size) = TEST_FIXTURE.new_file(op.clone());
98
+ let (offset, length) = gen_offset_length(size);
99
+
100
+ op.write(&path, content.clone())
101
+ .await
102
+ .expect("write must succeed");
103
+
104
+ let bs = op
105
+ .read_with(&path)
106
+ .range(offset..offset + length)
107
+ .await?
108
+ .to_bytes();
109
+ assert_eq!(bs.len() as u64, length, "read size");
110
+ assert_eq!(
111
+ format!("{:x}", Sha256::digest(&bs)),
112
+ format!(
113
+ "{:x}",
114
+ Sha256::digest(&content[offset as usize..(offset + length) as usize])
115
+ ),
116
+ "read content"
117
+ );
118
+
119
+ Ok(())
120
+ }
121
+
122
+ /// Read full content should match.
123
+ pub async fn test_reader(op: Operator) -> anyhow::Result<()> {
124
+ let (path, content, size) = TEST_FIXTURE.new_file(op.clone());
125
+
126
+ op.write(&path, content.clone())
127
+ .await
128
+ .expect("write must succeed");
129
+
130
+ // Reader.
131
+ let bs = op.reader(&path).await?.read(..).await?.to_bytes();
132
+ assert_eq!(size, bs.len(), "read size");
133
+ assert_eq!(
134
+ format!("{:x}", Sha256::digest(&bs)),
135
+ format!("{:x}", Sha256::digest(&content)),
136
+ "read content"
137
+ );
138
+
139
+ // Bytes Stream
140
+ let bs = op
141
+ .reader(&path)
142
+ .await?
143
+ .into_bytes_stream(..)
144
+ .await?
145
+ .try_fold(Vec::new(), |mut acc, chunk| {
146
+ acc.extend_from_slice(&chunk);
147
+ async { Ok(acc) }
148
+ })
149
+ .await?;
150
+ assert_eq!(size, bs.len(), "read size");
151
+ assert_eq!(
152
+ format!("{:x}", Sha256::digest(&bs)),
153
+ format!("{:x}", Sha256::digest(&content)),
154
+ "read content"
155
+ );
156
+
157
+ // Futures Reader
158
+ let mut futures_reader = op
159
+ .reader(&path)
160
+ .await?
161
+ .into_futures_async_read(0..size as u64)
162
+ .await?;
163
+ let mut bs = Vec::new();
164
+ futures_reader.read_to_end(&mut bs).await?;
165
+ assert_eq!(size, bs.len(), "read size");
166
+ assert_eq!(
167
+ format!("{:x}", Sha256::digest(&bs)),
168
+ format!("{:x}", Sha256::digest(&content)),
169
+ "read content"
170
+ );
171
+
172
+ Ok(())
173
+ }
174
+
175
+ /// Read not exist file should return NotFound
176
+ pub async fn test_read_not_exist(op: Operator) -> anyhow::Result<()> {
177
+ let path = uuid::Uuid::new_v4().to_string();
178
+
179
+ let bs = op.read(&path).await;
180
+ assert!(bs.is_err());
181
+ assert_eq!(bs.unwrap_err().kind(), ErrorKind::NotFound);
182
+
183
+ Ok(())
184
+ }
185
+
186
+ /// Reader with if_match should match, else get a ConditionNotMatch error.
187
+ pub async fn test_reader_with_if_match(op: Operator) -> anyhow::Result<()> {
188
+ if !op.info().full_capability().read_with_if_match {
189
+ return Ok(());
190
+ }
191
+
192
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
193
+
194
+ op.write(&path, content.clone())
195
+ .await
196
+ .expect("write must succeed");
197
+
198
+ let meta = op.stat(&path).await?;
199
+
200
+ let reader = op.reader_with(&path).if_match("\"invalid_etag\"").await?;
201
+ let res = reader.read(..).await;
202
+ assert!(res.is_err());
203
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
204
+
205
+ let reader = op
206
+ .reader_with(&path)
207
+ .if_match(meta.etag().expect("etag must exist"))
208
+ .await?;
209
+
210
+ let bs = reader.read(..).await.expect("read must succeed").to_bytes();
211
+ assert_eq!(bs, content);
212
+
213
+ Ok(())
214
+ }
215
+
216
+ /// Read with if_match should match, else get a ConditionNotMatch error.
217
+ pub async fn test_read_with_if_match(op: Operator) -> anyhow::Result<()> {
218
+ if !op.info().full_capability().read_with_if_match {
219
+ return Ok(());
220
+ }
221
+
222
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
223
+
224
+ op.write(&path, content.clone())
225
+ .await
226
+ .expect("write must succeed");
227
+
228
+ let meta = op.stat(&path).await?;
229
+
230
+ let res = op.read_with(&path).if_match("\"invalid_etag\"").await;
231
+ assert!(res.is_err());
232
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
233
+
234
+ let bs = op
235
+ .read_with(&path)
236
+ .if_match(meta.etag().expect("etag must exist"))
237
+ .await
238
+ .expect("read must succeed")
239
+ .to_bytes();
240
+ assert_eq!(bs, content);
241
+
242
+ Ok(())
243
+ }
244
+
245
+ /// Reader with if_none_match should match, else get a ConditionNotMatch error.
246
+ pub async fn test_reader_with_if_none_match(op: Operator) -> anyhow::Result<()> {
247
+ if !op.info().full_capability().read_with_if_none_match {
248
+ return Ok(());
249
+ }
250
+
251
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
252
+
253
+ op.write(&path, content.clone())
254
+ .await
255
+ .expect("write must succeed");
256
+
257
+ let meta = op.stat(&path).await?;
258
+
259
+ let reader = op
260
+ .reader_with(&path)
261
+ .if_none_match(meta.etag().expect("etag must exist"))
262
+ .await?;
263
+ let res = reader.read(..).await;
264
+
265
+ assert!(res.is_err());
266
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
267
+
268
+ let reader = op
269
+ .reader_with(&path)
270
+ .if_none_match("\"invalid_etag\"")
271
+ .await?;
272
+ let bs = reader.read(..).await.expect("read must succeed").to_bytes();
273
+ assert_eq!(bs, content);
274
+
275
+ Ok(())
276
+ }
277
+
278
+ /// Reader with if_modified_since should match, otherwise, a ConditionNotMatch error will be returned.
279
+ pub async fn test_reader_with_if_modified_since(op: Operator) -> anyhow::Result<()> {
280
+ if !op.info().full_capability().read_with_if_modified_since {
281
+ return Ok(());
282
+ }
283
+
284
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
285
+
286
+ op.write(&path, content.clone())
287
+ .await
288
+ .expect("write must succeed");
289
+ let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
290
+
291
+ let since = last_modified_time - chrono::Duration::seconds(1);
292
+ let reader = op.reader_with(&path).if_modified_since(since).await?;
293
+ let bs = reader.read(..).await?.to_bytes();
294
+ assert_eq!(bs, content);
295
+
296
+ sleep(Duration::from_secs(1)).await;
297
+
298
+ let since = last_modified_time + chrono::Duration::seconds(1);
299
+ let reader = op.reader_with(&path).if_modified_since(since).await?;
300
+ let res = reader.read(..).await;
301
+ assert!(res.is_err());
302
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
303
+
304
+ Ok(())
305
+ }
306
+
307
+ /// Reader with if_unmodified_since should match, otherwise, a ConditionNotMatch error will be returned.
308
+ pub async fn test_reader_with_if_unmodified_since(op: Operator) -> anyhow::Result<()> {
309
+ if !op.info().full_capability().read_with_if_unmodified_since {
310
+ return Ok(());
311
+ }
312
+
313
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
314
+
315
+ op.write(&path, content.clone())
316
+ .await
317
+ .expect("write must succeed");
318
+ let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
319
+
320
+ let since = last_modified_time - chrono::Duration::seconds(1);
321
+ let reader = op.reader_with(&path).if_unmodified_since(since).await?;
322
+ let res = reader.read(..).await;
323
+ assert!(res.is_err());
324
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
325
+
326
+ sleep(Duration::from_secs(1)).await;
327
+
328
+ let since = last_modified_time + chrono::Duration::seconds(1);
329
+ let reader = op.reader_with(&path).if_unmodified_since(since).await?;
330
+ let bs = reader.read(..).await?.to_bytes();
331
+ assert_eq!(bs, content);
332
+
333
+ Ok(())
334
+ }
335
+
336
+ /// Read with if_none_match should match, else get a ConditionNotMatch error.
337
+ pub async fn test_read_with_if_none_match(op: Operator) -> anyhow::Result<()> {
338
+ if !op.info().full_capability().read_with_if_none_match {
339
+ return Ok(());
340
+ }
341
+
342
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
343
+
344
+ op.write(&path, content.clone())
345
+ .await
346
+ .expect("write must succeed");
347
+
348
+ let meta = op.stat(&path).await?;
349
+
350
+ let res = op
351
+ .read_with(&path)
352
+ .if_none_match(meta.etag().expect("etag must exist"))
353
+ .await;
354
+ assert!(res.is_err());
355
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
356
+
357
+ let bs = op
358
+ .read_with(&path)
359
+ .if_none_match("\"invalid_etag\"")
360
+ .await
361
+ .expect("read must succeed")
362
+ .to_bytes();
363
+ assert_eq!(bs, content);
364
+
365
+ Ok(())
366
+ }
367
+
368
+ /// Read with dir path should return an error.
369
+ pub async fn test_read_with_dir_path(op: Operator) -> anyhow::Result<()> {
370
+ if !op.info().full_capability().create_dir {
371
+ return Ok(());
372
+ }
373
+
374
+ let path = TEST_FIXTURE.new_dir_path();
375
+
376
+ op.create_dir(&path).await.expect("write must succeed");
377
+
378
+ let result = op.read(&path).await;
379
+ assert!(result.is_err());
380
+ assert_eq!(result.unwrap_err().kind(), ErrorKind::IsADirectory);
381
+
382
+ Ok(())
383
+ }
384
+
385
+ /// Read file with special chars should succeed.
386
+ pub async fn test_read_with_special_chars(op: Operator) -> anyhow::Result<()> {
387
+ // Ignore test for atomicserver until https://github.com/atomicdata-dev/atomic-server/issues/663 addressed.
388
+ if op.info().scheme() == opendal::Scheme::Atomicserver {
389
+ warn!("ignore test for atomicserver until https://github.com/atomicdata-dev/atomic-server/issues/663 is resolved");
390
+ return Ok(());
391
+ }
392
+
393
+ let path = format!("{} !@#$%^&()_+-=;',.txt", uuid::Uuid::new_v4());
394
+ let (path, content, size) = TEST_FIXTURE.new_file_with_path(op.clone(), &path);
395
+
396
+ op.write(&path, content.clone())
397
+ .await
398
+ .expect("write must succeed");
399
+
400
+ let bs = op.read(&path).await?.to_bytes();
401
+ assert_eq!(size, bs.len(), "read size");
402
+ assert_eq!(
403
+ format!("{:x}", Sha256::digest(&bs)),
404
+ format!("{:x}", Sha256::digest(&content)),
405
+ "read content"
406
+ );
407
+
408
+ Ok(())
409
+ }
410
+
411
+ /// Read file with override-cache-control should succeed.
412
+ pub async fn test_read_with_override_cache_control(op: Operator) -> anyhow::Result<()> {
413
+ if !(op.info().full_capability().read_with_override_cache_control
414
+ && op.info().full_capability().presign)
415
+ {
416
+ return Ok(());
417
+ }
418
+
419
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
420
+
421
+ op.write(&path, content.clone())
422
+ .await
423
+ .expect("write must succeed");
424
+
425
+ let target_cache_control = "no-cache, no-store, must-revalidate";
426
+ let signed_req = op
427
+ .presign_read_with(&path, Duration::from_secs(60))
428
+ .override_cache_control(target_cache_control)
429
+ .await
430
+ .expect("sign must succeed");
431
+
432
+ let client = reqwest::Client::new();
433
+ let mut req = client.request(
434
+ signed_req.method().clone(),
435
+ Url::from_str(&signed_req.uri().to_string()).expect("must be valid url"),
436
+ );
437
+ for (k, v) in signed_req.header() {
438
+ req = req.header(k, v);
439
+ }
440
+
441
+ let resp = req.send().await.expect("send must succeed");
442
+
443
+ assert_eq!(resp.status(), StatusCode::OK);
444
+ assert_eq!(
445
+ resp.headers()
446
+ .get("cache-control")
447
+ .expect("cache-control header must exist")
448
+ .to_str()
449
+ .expect("cache-control header must be string"),
450
+ target_cache_control
451
+ );
452
+
453
+ Ok(())
454
+ }
455
+
456
+ /// Read file with override_content_disposition should succeed.
457
+ pub async fn test_read_with_override_content_disposition(op: Operator) -> anyhow::Result<()> {
458
+ if !(op
459
+ .info()
460
+ .full_capability()
461
+ .read_with_override_content_disposition
462
+ && op.info().full_capability().presign)
463
+ {
464
+ return Ok(());
465
+ }
466
+
467
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
468
+
469
+ op.write(&path, content.clone())
470
+ .await
471
+ .expect("write must succeed");
472
+
473
+ let target_content_disposition = "attachment; filename=foo.txt";
474
+
475
+ let signed_req = op
476
+ .presign_read_with(&path, Duration::from_secs(60))
477
+ .override_content_disposition(target_content_disposition)
478
+ .await
479
+ .expect("presign must succeed");
480
+
481
+ let client = reqwest::Client::new();
482
+ let mut req = client.request(
483
+ signed_req.method().clone(),
484
+ Url::from_str(&signed_req.uri().to_string()).expect("must be valid url"),
485
+ );
486
+ for (k, v) in signed_req.header() {
487
+ req = req.header(k, v);
488
+ }
489
+
490
+ let resp = req.send().await.expect("send must succeed");
491
+
492
+ assert_eq!(resp.status(), StatusCode::OK);
493
+ assert_eq!(
494
+ resp.headers()
495
+ .get(http::header::CONTENT_DISPOSITION)
496
+ .expect("content-disposition header must exist")
497
+ .to_str()
498
+ .expect("content-disposition header must be string"),
499
+ target_content_disposition
500
+ );
501
+ assert_eq!(resp.bytes().await?, content);
502
+
503
+ Ok(())
504
+ }
505
+
506
+ /// Read file with override_content_type should succeed.
507
+ pub async fn test_read_with_override_content_type(op: Operator) -> anyhow::Result<()> {
508
+ if !(op.info().full_capability().read_with_override_content_type
509
+ && op.info().full_capability().presign)
510
+ {
511
+ return Ok(());
512
+ }
513
+
514
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
515
+
516
+ op.write(&path, content.clone())
517
+ .await
518
+ .expect("write must succeed");
519
+
520
+ let target_content_type = "application/opendal";
521
+
522
+ let signed_req = op
523
+ .presign_read_with(&path, Duration::from_secs(60))
524
+ .override_content_type(target_content_type)
525
+ .await
526
+ .expect("presign must succeed");
527
+
528
+ let client = reqwest::Client::new();
529
+ let mut req = client.request(
530
+ signed_req.method().clone(),
531
+ Url::from_str(&signed_req.uri().to_string()).expect("must be valid url"),
532
+ );
533
+ for (k, v) in signed_req.header() {
534
+ req = req.header(k, v);
535
+ }
536
+
537
+ let resp = req.send().await.expect("send must succeed");
538
+
539
+ assert_eq!(resp.status(), StatusCode::OK);
540
+ assert_eq!(
541
+ resp.headers()
542
+ .get(http::header::CONTENT_TYPE)
543
+ .expect("content-type header must exist")
544
+ .to_str()
545
+ .expect("content-type header must be string"),
546
+ target_content_type
547
+ );
548
+ assert_eq!(resp.bytes().await?, content);
549
+
550
+ Ok(())
551
+ }
552
+
553
+ /// Read with if_modified_since should match, otherwise, a ConditionNotMatch error will be returned.
554
+ pub async fn test_read_with_if_modified_since(op: Operator) -> anyhow::Result<()> {
555
+ if !op.info().full_capability().read_with_if_modified_since {
556
+ return Ok(());
557
+ }
558
+
559
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
560
+
561
+ op.write(&path, content.clone())
562
+ .await
563
+ .expect("write must succeed");
564
+ let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
565
+
566
+ let since = last_modified_time - chrono::Duration::seconds(1);
567
+ let bs = op
568
+ .read_with(&path)
569
+ .if_modified_since(since)
570
+ .await?
571
+ .to_bytes();
572
+ assert_eq!(bs, content);
573
+
574
+ sleep(Duration::from_secs(1)).await;
575
+
576
+ let since = last_modified_time + chrono::Duration::seconds(1);
577
+ let res = op.read_with(&path).if_modified_since(since).await;
578
+ assert!(res.is_err());
579
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
580
+
581
+ Ok(())
582
+ }
583
+
584
+ /// Read with if_unmodified_since should match, otherwise, a ConditionNotMatch error will be returned.
585
+ pub async fn test_read_with_if_unmodified_since(op: Operator) -> anyhow::Result<()> {
586
+ if !op.info().full_capability().read_with_if_unmodified_since {
587
+ return Ok(());
588
+ }
589
+
590
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
591
+
592
+ op.write(&path, content.clone())
593
+ .await
594
+ .expect("write must succeed");
595
+ let last_modified = op.stat(&path).await?.last_modified().unwrap();
596
+
597
+ let since = last_modified - chrono::Duration::seconds(3600);
598
+ let res = op.read_with(&path).if_unmodified_since(since).await;
599
+ assert!(res.is_err());
600
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
601
+
602
+ sleep(Duration::from_secs(1)).await;
603
+
604
+ let since = last_modified + chrono::Duration::seconds(1);
605
+ let bs = op
606
+ .read_with(&path)
607
+ .if_unmodified_since(since)
608
+ .await?
609
+ .to_bytes();
610
+ assert_eq!(bs, content);
611
+
612
+ Ok(())
613
+ }
614
+
615
+ /// Read full content should match.
616
+ pub async fn test_read_only_read_full(op: Operator) -> anyhow::Result<()> {
617
+ let bs = op.read("normal_file.txt").await?.to_bytes();
618
+ assert_eq!(bs.len(), 30482, "read size");
619
+ assert_eq!(
620
+ format!("{:x}", Sha256::digest(&bs)),
621
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
622
+ "read content"
623
+ );
624
+
625
+ Ok(())
626
+ }
627
+
628
+ /// Read full content should match.
629
+ pub async fn test_read_only_read_full_with_special_chars(op: Operator) -> anyhow::Result<()> {
630
+ let bs = op
631
+ .read("special_file !@#$%^&()_+-=;',.txt")
632
+ .await?
633
+ .to_bytes();
634
+ assert_eq!(bs.len(), 30482, "read size");
635
+ assert_eq!(
636
+ format!("{:x}", Sha256::digest(&bs)),
637
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
638
+ "read content"
639
+ );
640
+
641
+ Ok(())
642
+ }
643
+
644
+ /// Read full content should match.
645
+ pub async fn test_read_only_read_with_range(op: Operator) -> anyhow::Result<()> {
646
+ let bs = op
647
+ .read_with("normal_file.txt")
648
+ .range(1024..2048)
649
+ .await?
650
+ .to_bytes();
651
+ assert_eq!(bs.len(), 1024, "read size");
652
+ assert_eq!(
653
+ format!("{:x}", Sha256::digest(&bs)),
654
+ "330c6d57fdc1119d6021b37714ca5ad0ede12edd484f66be799a5cff59667034",
655
+ "read content"
656
+ );
657
+
658
+ Ok(())
659
+ }
660
+
661
+ /// Read not exist file should return NotFound
662
+ pub async fn test_read_only_read_not_exist(op: Operator) -> anyhow::Result<()> {
663
+ let path = uuid::Uuid::new_v4().to_string();
664
+
665
+ let bs = op.read(&path).await;
666
+ assert!(bs.is_err());
667
+ assert_eq!(bs.unwrap_err().kind(), ErrorKind::NotFound);
668
+
669
+ Ok(())
670
+ }
671
+
672
+ /// Read with dir path should return an error.
673
+ pub async fn test_read_only_read_with_dir_path(op: Operator) -> anyhow::Result<()> {
674
+ let path = format!("{}/", uuid::Uuid::new_v4());
675
+
676
+ let result = op.read(&path).await;
677
+ assert!(result.is_err());
678
+ assert_eq!(result.unwrap_err().kind(), ErrorKind::IsADirectory);
679
+
680
+ Ok(())
681
+ }
682
+
683
+ /// Reader with if_match should match, else get a ConditionNotMatch error.
684
+ pub async fn test_reader_only_read_with_if_match(op: Operator) -> anyhow::Result<()> {
685
+ if !op.info().full_capability().read_with_if_match {
686
+ return Ok(());
687
+ }
688
+
689
+ let path = "normal_file.txt";
690
+
691
+ let meta = op.stat(path).await?;
692
+
693
+ let reader = op.reader_with(path).if_match("invalid_etag").await?;
694
+ let res = reader.read(..).await;
695
+ assert!(res.is_err());
696
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
697
+
698
+ let reader = op
699
+ .reader_with(path)
700
+ .if_match(meta.etag().expect("etag must exist"))
701
+ .await?;
702
+
703
+ let bs = reader.read(..).await.expect("read must succeed").to_bytes();
704
+
705
+ assert_eq!(bs.len(), 30482, "read size");
706
+ assert_eq!(
707
+ format!("{:x}", Sha256::digest(&bs)),
708
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
709
+ "read content"
710
+ );
711
+
712
+ Ok(())
713
+ }
714
+
715
+ /// Read with if_match should match, else get a ConditionNotMatch error.
716
+ pub async fn test_read_only_read_with_if_match(op: Operator) -> anyhow::Result<()> {
717
+ if !op.info().full_capability().read_with_if_match {
718
+ return Ok(());
719
+ }
720
+
721
+ let path = "normal_file.txt";
722
+
723
+ let meta = op.stat(path).await?;
724
+
725
+ let res = op.read_with(path).if_match("invalid_etag").await;
726
+ assert!(res.is_err());
727
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
728
+
729
+ let bs = op
730
+ .read_with(path)
731
+ .if_match(meta.etag().expect("etag must exist"))
732
+ .await
733
+ .expect("read must succeed")
734
+ .to_bytes();
735
+ assert_eq!(bs.len(), 30482, "read size");
736
+ assert_eq!(
737
+ format!("{:x}", Sha256::digest(&bs)),
738
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
739
+ "read content"
740
+ );
741
+
742
+ Ok(())
743
+ }
744
+
745
+ /// Reader with if_none_match should match, else get a ConditionNotMatch error.
746
+ pub async fn test_reader_only_read_with_if_none_match(op: Operator) -> anyhow::Result<()> {
747
+ if !op.info().full_capability().read_with_if_none_match {
748
+ return Ok(());
749
+ }
750
+
751
+ let path = "normal_file.txt";
752
+
753
+ let meta = op.stat(path).await?;
754
+
755
+ let reader = op
756
+ .reader_with(path)
757
+ .if_none_match(meta.etag().expect("etag must exist"))
758
+ .await?;
759
+
760
+ let res = reader.read(..).await;
761
+ assert!(res.is_err());
762
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
763
+
764
+ let reader = op.reader_with(path).if_none_match("invalid_etag").await?;
765
+ let bs = reader.read(..).await.expect("read must succeed").to_bytes();
766
+
767
+ assert_eq!(bs.len(), 30482, "read size");
768
+ assert_eq!(
769
+ format!("{:x}", Sha256::digest(&bs)),
770
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
771
+ "read content"
772
+ );
773
+
774
+ Ok(())
775
+ }
776
+
777
+ /// Read with if_none_match should match, else get a ConditionNotMatch error.
778
+ pub async fn test_read_only_read_with_if_none_match(op: Operator) -> anyhow::Result<()> {
779
+ if !op.info().full_capability().read_with_if_none_match {
780
+ return Ok(());
781
+ }
782
+
783
+ let path = "normal_file.txt";
784
+
785
+ let meta = op.stat(path).await?;
786
+
787
+ let res = op
788
+ .read_with(path)
789
+ .if_none_match(meta.etag().expect("etag must exist"))
790
+ .await;
791
+ assert!(res.is_err());
792
+ assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
793
+
794
+ let bs = op
795
+ .read_with(path)
796
+ .if_none_match("invalid_etag")
797
+ .await
798
+ .expect("read must succeed")
799
+ .to_bytes();
800
+ assert_eq!(bs.len(), 30482, "read size");
801
+ assert_eq!(
802
+ format!("{:x}", Sha256::digest(&bs)),
803
+ "943048ba817cdcd786db07d1f42d5500da7d10541c2f9353352cd2d3f66617e5",
804
+ "read content"
805
+ );
806
+
807
+ Ok(())
808
+ }
809
+
810
+ pub async fn test_read_with_version(op: Operator) -> anyhow::Result<()> {
811
+ if !op.info().full_capability().read_with_version {
812
+ return Ok(());
813
+ }
814
+
815
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
816
+ op.write(path.as_str(), content.clone())
817
+ .await
818
+ .expect("write must success");
819
+ let meta = op.stat(path.as_str()).await.expect("stat must success");
820
+ let version = meta.version().expect("must have version");
821
+
822
+ let data = op
823
+ .read_with(path.as_str())
824
+ .version(version)
825
+ .await
826
+ .expect("read must success");
827
+ assert_eq!(content, data.to_vec());
828
+
829
+ op.write(path.as_str(), "1")
830
+ .await
831
+ .expect("write must success");
832
+
833
+ // After writing new data, we can still read the first version data
834
+ let second_data = op
835
+ .read_with(path.as_str())
836
+ .version(version)
837
+ .await
838
+ .expect("read must success");
839
+ assert_eq!(content, second_data.to_vec());
840
+
841
+ Ok(())
842
+ }
843
+
844
+ pub async fn test_read_with_not_existing_version(op: Operator) -> anyhow::Result<()> {
845
+ if !op.info().full_capability().read_with_version {
846
+ return Ok(());
847
+ }
848
+
849
+ // retrieve a valid version
850
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
851
+ op.write(path.as_str(), content.clone())
852
+ .await
853
+ .expect("write must success");
854
+ let version = op
855
+ .stat(path.as_str())
856
+ .await
857
+ .expect("stat must success")
858
+ .version()
859
+ .expect("must have version")
860
+ .to_string();
861
+
862
+ let (path, content, _) = TEST_FIXTURE.new_file(op.clone());
863
+ op.write(path.as_str(), content)
864
+ .await
865
+ .expect("write must success");
866
+ let ret = op.read_with(path.as_str()).version(&version).await;
867
+ assert!(ret.is_err());
868
+ assert_eq!(ret.unwrap_err().kind(), ErrorKind::NotFound);
869
+
870
+ Ok(())
871
+ }