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,276 @@
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::convert::Infallible;
19
+ use std::fmt::Debug;
20
+ use std::fmt::Formatter;
21
+ use std::future;
22
+ use std::mem;
23
+ use std::ops::Deref;
24
+ use std::pin::Pin;
25
+ use std::str::FromStr;
26
+ use std::sync::Arc;
27
+ use std::sync::LazyLock;
28
+ use std::task::Context;
29
+ use std::task::Poll;
30
+
31
+ use bytes::Bytes;
32
+ use futures::Future;
33
+ use futures::TryStreamExt;
34
+ use http::Request;
35
+ use http::Response;
36
+ use http_body::Frame;
37
+ use http_body::SizeHint;
38
+ use raw::oio::Read;
39
+
40
+ use super::parse_content_encoding;
41
+ use super::parse_content_length;
42
+ use super::HttpBody;
43
+ use crate::raw::*;
44
+ use crate::*;
45
+
46
+ /// Http client used across opendal for loading credentials.
47
+ /// This is merely a temporary solution because reqsign requires a reqwest client to be passed.
48
+ /// We will remove it after the next major version of reqsign, which will enable users to provide their own client.
49
+ #[allow(dead_code)]
50
+ pub(crate) static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> =
51
+ LazyLock::new(reqwest::Client::new);
52
+
53
+ /// HttpFetcher is a type erased [`HttpFetch`].
54
+ pub type HttpFetcher = Arc<dyn HttpFetchDyn>;
55
+
56
+ /// A HTTP client instance for OpenDAL's services.
57
+ ///
58
+ /// # Notes
59
+ ///
60
+ /// * A http client must support redirections that follows 3xx response.
61
+ #[derive(Clone)]
62
+ pub struct HttpClient {
63
+ fetcher: HttpFetcher,
64
+ }
65
+
66
+ /// We don't want users to know details about our clients.
67
+ impl Debug for HttpClient {
68
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
69
+ f.debug_struct("HttpClient").finish()
70
+ }
71
+ }
72
+
73
+ impl Default for HttpClient {
74
+ fn default() -> Self {
75
+ Self {
76
+ fetcher: Arc::new(GLOBAL_REQWEST_CLIENT.clone()),
77
+ }
78
+ }
79
+ }
80
+
81
+ impl HttpClient {
82
+ /// Create a new http client in async context.
83
+ pub fn new() -> Result<Self> {
84
+ Ok(Self::default())
85
+ }
86
+
87
+ /// Construct `Self` with given [`reqwest::Client`]
88
+ pub fn with(client: impl HttpFetch) -> Self {
89
+ let fetcher = Arc::new(client);
90
+ Self { fetcher }
91
+ }
92
+
93
+ /// Get the inner http client.
94
+ pub(crate) fn into_inner(self) -> HttpFetcher {
95
+ self.fetcher
96
+ }
97
+
98
+ /// Build a new http client in async context.
99
+ #[deprecated]
100
+ pub fn build(builder: reqwest::ClientBuilder) -> Result<Self> {
101
+ let client = builder.build().map_err(|err| {
102
+ Error::new(ErrorKind::Unexpected, "http client build failed").set_source(err)
103
+ })?;
104
+ let fetcher = Arc::new(client);
105
+ Ok(Self { fetcher })
106
+ }
107
+
108
+ /// Send a request and consume response.
109
+ pub async fn send(&self, req: Request<Buffer>) -> Result<Response<Buffer>> {
110
+ let (parts, mut body) = self.fetch(req).await?.into_parts();
111
+ let buffer = body.read_all().await?;
112
+ Ok(Response::from_parts(parts, buffer))
113
+ }
114
+
115
+ /// Fetch a request and return a streamable [`HttpBody`].
116
+ ///
117
+ /// Services can use [`HttpBody`] as [`Access::Read`].
118
+ pub async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
119
+ self.fetcher.fetch(req).await
120
+ }
121
+ }
122
+
123
+ /// HttpFetch is the trait to fetch a request in async way.
124
+ /// User should implement this trait to provide their own http client.
125
+ pub trait HttpFetch: Send + Sync + Unpin + 'static {
126
+ /// Fetch a request in async way.
127
+ fn fetch(
128
+ &self,
129
+ req: Request<Buffer>,
130
+ ) -> impl Future<Output = Result<Response<HttpBody>>> + MaybeSend;
131
+ }
132
+
133
+ /// HttpFetchDyn is the dyn version of [`HttpFetch`]
134
+ /// which make it possible to use as `Arc<dyn HttpFetchDyn>`.
135
+ /// User should never implement this trait, but use `HttpFetch` instead.
136
+ pub trait HttpFetchDyn: Send + Sync + Unpin + 'static {
137
+ /// The dyn version of [`HttpFetch::fetch`].
138
+ ///
139
+ /// This function returns a boxed future to make it object safe.
140
+ fn fetch_dyn(&self, req: Request<Buffer>) -> BoxedFuture<'_, Result<Response<HttpBody>>>;
141
+ }
142
+
143
+ impl<T: HttpFetch + ?Sized> HttpFetchDyn for T {
144
+ fn fetch_dyn(&self, req: Request<Buffer>) -> BoxedFuture<'_, Result<Response<HttpBody>>> {
145
+ Box::pin(self.fetch(req))
146
+ }
147
+ }
148
+
149
+ impl<T: HttpFetchDyn + ?Sized> HttpFetch for Arc<T> {
150
+ async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
151
+ self.deref().fetch_dyn(req).await
152
+ }
153
+ }
154
+
155
+ impl HttpFetch for reqwest::Client {
156
+ async fn fetch(&self, req: Request<Buffer>) -> Result<Response<HttpBody>> {
157
+ // Uri stores all string alike data in `Bytes` which means
158
+ // the clone here is cheap.
159
+ let uri = req.uri().clone();
160
+ let is_head = req.method() == http::Method::HEAD;
161
+
162
+ let (parts, body) = req.into_parts();
163
+
164
+ let url = reqwest::Url::from_str(&uri.to_string()).map_err(|err| {
165
+ Error::new(ErrorKind::Unexpected, "request url is invalid")
166
+ .with_operation("http_util::Client::send::fetch")
167
+ .with_context("url", uri.to_string())
168
+ .set_source(err)
169
+ })?;
170
+
171
+ let mut req_builder = self.request(parts.method, url).headers(parts.headers);
172
+
173
+ // Client under wasm doesn't support set version.
174
+ #[cfg(not(target_arch = "wasm32"))]
175
+ {
176
+ req_builder = req_builder.version(parts.version);
177
+ }
178
+
179
+ // Don't set body if body is empty.
180
+ if !body.is_empty() {
181
+ #[cfg(not(target_arch = "wasm32"))]
182
+ {
183
+ req_builder = req_builder.body(reqwest::Body::wrap(HttpBufferBody(body)))
184
+ }
185
+ #[cfg(target_arch = "wasm32")]
186
+ {
187
+ req_builder = req_builder.body(reqwest::Body::from(body.to_bytes()))
188
+ }
189
+ }
190
+
191
+ let mut resp = req_builder.send().await.map_err(|err| {
192
+ Error::new(ErrorKind::Unexpected, "send http request")
193
+ .with_operation("http_util::Client::send")
194
+ .with_context("url", uri.to_string())
195
+ .with_temporary(is_temporary_error(&err))
196
+ .set_source(err)
197
+ })?;
198
+
199
+ // Get content length from header so that we can check it.
200
+ //
201
+ // - If the request method is HEAD, we will ignore content length.
202
+ // - If response contains content_encoding, we should omit its content length.
203
+ let content_length = if is_head || parse_content_encoding(resp.headers())?.is_some() {
204
+ None
205
+ } else {
206
+ parse_content_length(resp.headers())?
207
+ };
208
+
209
+ let mut hr = Response::builder()
210
+ .status(resp.status())
211
+ // Insert uri into response extension so that we can fetch
212
+ // it later.
213
+ .extension(uri.clone());
214
+
215
+ // Response builder under wasm doesn't support set version.
216
+ #[cfg(not(target_arch = "wasm32"))]
217
+ {
218
+ hr = hr.version(resp.version());
219
+ }
220
+
221
+ // Swap headers directly instead of copy the entire map.
222
+ mem::swap(hr.headers_mut().unwrap(), resp.headers_mut());
223
+
224
+ let bs = HttpBody::new(
225
+ resp.bytes_stream()
226
+ .try_filter(|v| future::ready(!v.is_empty()))
227
+ .map_ok(Buffer::from)
228
+ .map_err(move |err| {
229
+ Error::new(ErrorKind::Unexpected, "read data from http response")
230
+ .with_operation("http_util::Client::send")
231
+ .with_context("url", uri.to_string())
232
+ .with_temporary(is_temporary_error(&err))
233
+ .set_source(err)
234
+ }),
235
+ content_length,
236
+ );
237
+
238
+ let resp = hr.body(bs).expect("response must build succeed");
239
+ Ok(resp)
240
+ }
241
+ }
242
+
243
+ #[inline]
244
+ fn is_temporary_error(err: &reqwest::Error) -> bool {
245
+ // error sending request
246
+ err.is_request()||
247
+ // request or response body error
248
+ err.is_body() ||
249
+ // error decoding response body, for example, connection reset.
250
+ err.is_decode()
251
+ }
252
+
253
+ struct HttpBufferBody(Buffer);
254
+
255
+ impl http_body::Body for HttpBufferBody {
256
+ type Data = Bytes;
257
+ type Error = Infallible;
258
+
259
+ fn poll_frame(
260
+ mut self: Pin<&mut Self>,
261
+ _: &mut Context<'_>,
262
+ ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
263
+ match self.0.next() {
264
+ Some(bs) => Poll::Ready(Some(Ok(Frame::data(bs)))),
265
+ None => Poll::Ready(None),
266
+ }
267
+ }
268
+
269
+ fn is_end_stream(&self) -> bool {
270
+ self.0.is_empty()
271
+ }
272
+
273
+ fn size_hint(&self) -> SizeHint {
274
+ SizeHint::with_exact(self.0.len() as u64)
275
+ }
276
+ }
@@ -0,0 +1,68 @@
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 http::response::Parts;
19
+ use http::Uri;
20
+
21
+ use crate::Error;
22
+ use crate::ErrorKind;
23
+
24
+ /// Create a new error happened during building request.
25
+ pub fn new_request_build_error(err: http::Error) -> Error {
26
+ Error::new(ErrorKind::Unexpected, "building http request")
27
+ .with_operation("http::Request::build")
28
+ .set_source(err)
29
+ }
30
+
31
+ /// Create a new error happened during signing request.
32
+ pub fn new_request_credential_error(err: anyhow::Error) -> Error {
33
+ Error::new(
34
+ ErrorKind::Unexpected,
35
+ "loading credential to sign http request",
36
+ )
37
+ .set_temporary()
38
+ .with_operation("reqsign::LoadCredential")
39
+ .set_source(err)
40
+ }
41
+
42
+ /// Create a new error happened during signing request.
43
+ pub fn new_request_sign_error(err: anyhow::Error) -> Error {
44
+ Error::new(ErrorKind::Unexpected, "signing http request")
45
+ .with_operation("reqsign::Sign")
46
+ .set_source(err)
47
+ }
48
+
49
+ /// Add response context to error.
50
+ ///
51
+ /// This helper function will:
52
+ ///
53
+ /// - remove sensitive or useless headers from parts.
54
+ /// - fetch uri if parts extensions contains `Uri`.
55
+ pub fn with_error_response_context(mut err: Error, mut parts: Parts) -> Error {
56
+ if let Some(uri) = parts.extensions.get::<Uri>() {
57
+ err = err.with_context("uri", uri.to_string());
58
+ }
59
+
60
+ // The following headers may contains sensitive information.
61
+ parts.headers.remove("Set-Cookie");
62
+ parts.headers.remove("WWW-Authenticate");
63
+ parts.headers.remove("Proxy-Authenticate");
64
+
65
+ err = err.with_context("response", format!("{parts:?}"));
66
+
67
+ err
68
+ }
@@ -0,0 +1,356 @@
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::collections::HashMap;
19
+
20
+ use base64::engine::general_purpose;
21
+ use base64::Engine;
22
+ use chrono::DateTime;
23
+ use chrono::Utc;
24
+ use http::header::CACHE_CONTROL;
25
+ use http::header::CONTENT_DISPOSITION;
26
+ use http::header::CONTENT_ENCODING;
27
+ use http::header::CONTENT_LENGTH;
28
+ use http::header::CONTENT_RANGE;
29
+ use http::header::CONTENT_TYPE;
30
+ use http::header::ETAG;
31
+ use http::header::LAST_MODIFIED;
32
+ use http::header::LOCATION;
33
+ use http::HeaderMap;
34
+ use http::HeaderName;
35
+ use http::HeaderValue;
36
+ use md5::Digest;
37
+
38
+ use crate::raw::*;
39
+ use crate::EntryMode;
40
+ use crate::Error;
41
+ use crate::ErrorKind;
42
+ use crate::Metadata;
43
+ use crate::Result;
44
+
45
+ /// Parse redirect location from header map
46
+ ///
47
+ /// # Note
48
+ /// The returned value maybe a relative path, like `/index.html`, `/robots.txt`, etc.
49
+ pub fn parse_location(headers: &HeaderMap) -> Result<Option<&str>> {
50
+ parse_header_to_str(headers, LOCATION)
51
+ }
52
+
53
+ /// Parse cache control from header map.
54
+ ///
55
+ /// # Note
56
+ ///
57
+ /// The returned value is the raw string of `cache-control` header,
58
+ /// maybe `no-cache`, `max-age=3600`, etc.
59
+ pub fn parse_cache_control(headers: &HeaderMap) -> Result<Option<&str>> {
60
+ parse_header_to_str(headers, CACHE_CONTROL)
61
+ }
62
+
63
+ /// Parse content length from header map.
64
+ pub fn parse_content_length(headers: &HeaderMap) -> Result<Option<u64>> {
65
+ parse_header_to_str(headers, CONTENT_LENGTH)?
66
+ .map(|v| {
67
+ v.parse::<u64>().map_err(|e| {
68
+ Error::new(ErrorKind::Unexpected, "header value is not valid integer").set_source(e)
69
+ })
70
+ })
71
+ .transpose()
72
+ }
73
+
74
+ /// Parse content md5 from header map.
75
+ pub fn parse_content_md5(headers: &HeaderMap) -> Result<Option<&str>> {
76
+ parse_header_to_str(headers, "content-md5")
77
+ }
78
+
79
+ /// Parse content type from header map.
80
+ pub fn parse_content_type(headers: &HeaderMap) -> Result<Option<&str>> {
81
+ parse_header_to_str(headers, CONTENT_TYPE)
82
+ }
83
+
84
+ /// Parse content encoding from header map.
85
+ pub fn parse_content_encoding(headers: &HeaderMap) -> Result<Option<&str>> {
86
+ parse_header_to_str(headers, CONTENT_ENCODING)
87
+ }
88
+
89
+ /// Parse content range from header map.
90
+ pub fn parse_content_range(headers: &HeaderMap) -> Result<Option<BytesContentRange>> {
91
+ parse_header_to_str(headers, CONTENT_RANGE)?
92
+ .map(|v| v.parse())
93
+ .transpose()
94
+ }
95
+
96
+ /// Parse last modified from header map.
97
+ pub fn parse_last_modified(headers: &HeaderMap) -> Result<Option<DateTime<Utc>>> {
98
+ parse_header_to_str(headers, LAST_MODIFIED)?
99
+ .map(parse_datetime_from_rfc2822)
100
+ .transpose()
101
+ }
102
+
103
+ /// Parse etag from header map.
104
+ pub fn parse_etag(headers: &HeaderMap) -> Result<Option<&str>> {
105
+ parse_header_to_str(headers, ETAG)
106
+ }
107
+
108
+ /// Parse Content-Disposition for header map
109
+ pub fn parse_content_disposition(headers: &HeaderMap) -> Result<Option<&str>> {
110
+ parse_header_to_str(headers, CONTENT_DISPOSITION)
111
+ }
112
+
113
+ /// Parse multipart boundary from header map.
114
+ pub fn parse_multipart_boundary(headers: &HeaderMap) -> Result<Option<&str>> {
115
+ parse_header_to_str(headers, CONTENT_TYPE).map(|v| v.and_then(|v| v.split("boundary=").nth(1)))
116
+ }
117
+
118
+ /// Parse header value to string according to name.
119
+ #[inline]
120
+ pub fn parse_header_to_str<K>(headers: &HeaderMap, name: K) -> Result<Option<&str>>
121
+ where
122
+ HeaderName: TryFrom<K>,
123
+ {
124
+ let name = HeaderName::try_from(name).map_err(|_| {
125
+ Error::new(
126
+ ErrorKind::Unexpected,
127
+ "header name must be valid http header name but not",
128
+ )
129
+ .with_operation("http_util::parse_header_to_str")
130
+ })?;
131
+
132
+ let value = if let Some(v) = headers.get(&name) {
133
+ v
134
+ } else {
135
+ return Ok(None);
136
+ };
137
+
138
+ Ok(Some(value.to_str().map_err(|e| {
139
+ Error::new(
140
+ ErrorKind::Unexpected,
141
+ "header value must be valid utf-8 string but not",
142
+ )
143
+ .with_operation("http_util::parse_header_to_str")
144
+ .with_context("header_name", name.as_str())
145
+ .set_source(e)
146
+ })?))
147
+ }
148
+
149
+ /// parse_into_metadata will parse standards http headers into Metadata.
150
+ ///
151
+ /// # Notes
152
+ ///
153
+ /// parse_into_metadata only handles the standard behavior of http
154
+ /// headers. If services have their own logic, they should update the parsed
155
+ /// metadata on demand.
156
+ pub fn parse_into_metadata(path: &str, headers: &HeaderMap) -> Result<Metadata> {
157
+ let mode = if path.ends_with('/') {
158
+ EntryMode::DIR
159
+ } else {
160
+ EntryMode::FILE
161
+ };
162
+ let mut m = Metadata::new(mode);
163
+
164
+ if let Some(v) = parse_cache_control(headers)? {
165
+ m.set_cache_control(v);
166
+ }
167
+
168
+ if let Some(v) = parse_content_length(headers)? {
169
+ m.set_content_length(v);
170
+ }
171
+
172
+ if let Some(v) = parse_content_type(headers)? {
173
+ m.set_content_type(v);
174
+ }
175
+
176
+ if let Some(v) = parse_content_encoding(headers)? {
177
+ m.set_content_encoding(v);
178
+ }
179
+
180
+ if let Some(v) = parse_content_range(headers)? {
181
+ m.set_content_range(v);
182
+ }
183
+
184
+ if let Some(v) = parse_etag(headers)? {
185
+ m.set_etag(v);
186
+ }
187
+
188
+ if let Some(v) = parse_content_md5(headers)? {
189
+ m.set_content_md5(v);
190
+ }
191
+
192
+ if let Some(v) = parse_last_modified(headers)? {
193
+ m.set_last_modified(v);
194
+ }
195
+
196
+ if let Some(v) = parse_content_disposition(headers)? {
197
+ m.set_content_disposition(v);
198
+ }
199
+
200
+ Ok(m)
201
+ }
202
+
203
+ /// Parse prefixed headers and return a map with the prefix of each header removed.
204
+ pub fn parse_prefixed_headers(headers: &HeaderMap, prefix: &str) -> HashMap<String, String> {
205
+ headers
206
+ .iter()
207
+ .filter_map(|(name, value)| {
208
+ name.as_str().strip_prefix(prefix).and_then(|stripped_key| {
209
+ value
210
+ .to_str()
211
+ .ok()
212
+ .map(|parsed_value| (stripped_key.to_string(), parsed_value.to_string()))
213
+ })
214
+ })
215
+ .collect()
216
+ }
217
+
218
+ /// format content md5 header by given input.
219
+ pub fn format_content_md5(bs: &[u8]) -> String {
220
+ let mut hasher = md5::Md5::new();
221
+ hasher.update(bs);
222
+
223
+ general_purpose::STANDARD.encode(hasher.finalize())
224
+ }
225
+
226
+ /// format authorization header by basic auth.
227
+ ///
228
+ /// # Errors
229
+ ///
230
+ /// If input username is empty, function will return an unexpected error.
231
+ pub fn format_authorization_by_basic(username: &str, password: &str) -> Result<String> {
232
+ if username.is_empty() {
233
+ return Err(Error::new(
234
+ ErrorKind::Unexpected,
235
+ "can't build authorization header with empty username",
236
+ ));
237
+ }
238
+
239
+ let value = general_purpose::STANDARD.encode(format!("{username}:{password}"));
240
+
241
+ Ok(format!("Basic {value}"))
242
+ }
243
+
244
+ /// format authorization header by bearer token.
245
+ ///
246
+ /// # Errors
247
+ ///
248
+ /// If input token is empty, function will return an unexpected error.
249
+ pub fn format_authorization_by_bearer(token: &str) -> Result<String> {
250
+ if token.is_empty() {
251
+ return Err(Error::new(
252
+ ErrorKind::Unexpected,
253
+ "can't build authorization header with empty token",
254
+ ));
255
+ }
256
+
257
+ Ok(format!("Bearer {token}"))
258
+ }
259
+
260
+ /// Build header value from given string.
261
+ pub fn build_header_value(v: &str) -> Result<HeaderValue> {
262
+ HeaderValue::from_str(v).map_err(|e| {
263
+ Error::new(
264
+ ErrorKind::ConfigInvalid,
265
+ "header value contains invalid characters",
266
+ )
267
+ .with_operation("http_util::build_header_value")
268
+ .set_source(e)
269
+ })
270
+ }
271
+
272
+ #[cfg(test)]
273
+ mod tests {
274
+ use super::*;
275
+
276
+ /// Test cases is from https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html
277
+ #[test]
278
+ fn test_format_content_md5() {
279
+ let cases = vec![(
280
+ r#"<Delete>
281
+ <Object>
282
+ <Key>sample1.txt</Key>
283
+ </Object>
284
+ <Object>
285
+ <Key>sample2.txt</Key>
286
+ </Object>
287
+ </Delete>"#,
288
+ "WOctCY1SS662e7ziElh4cw==",
289
+ )];
290
+
291
+ for (input, expected) in cases {
292
+ let actual = format_content_md5(input.as_bytes());
293
+
294
+ assert_eq!(actual, expected)
295
+ }
296
+ }
297
+
298
+ /// Test cases is borrowed from
299
+ ///
300
+ /// - RFC2617: https://datatracker.ietf.org/doc/html/rfc2617#section-2
301
+ /// - MDN: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
302
+ #[test]
303
+ fn test_format_authorization_by_basic() {
304
+ let cases = vec![
305
+ ("aladdin", "opensesame", "Basic YWxhZGRpbjpvcGVuc2VzYW1l"),
306
+ ("aladdin", "", "Basic YWxhZGRpbjo="),
307
+ (
308
+ "Aladdin",
309
+ "open sesame",
310
+ "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
311
+ ),
312
+ ("Aladdin", "", "Basic QWxhZGRpbjo="),
313
+ ];
314
+
315
+ for (username, password, expected) in cases {
316
+ let actual =
317
+ format_authorization_by_basic(username, password).expect("format must success");
318
+
319
+ assert_eq!(actual, expected)
320
+ }
321
+ }
322
+
323
+ /// Test cases is borrowed from
324
+ ///
325
+ /// - RFC6750: https://datatracker.ietf.org/doc/html/rfc6750
326
+ #[test]
327
+ fn test_format_authorization_by_bearer() {
328
+ let cases = vec![("mF_9.B5f-4.1JqM", "Bearer mF_9.B5f-4.1JqM")];
329
+
330
+ for (token, expected) in cases {
331
+ let actual = format_authorization_by_bearer(token).expect("format must success");
332
+
333
+ assert_eq!(actual, expected)
334
+ }
335
+ }
336
+
337
+ #[test]
338
+ fn test_parse_multipart_boundary() {
339
+ let cases = vec![
340
+ (
341
+ "multipart/mixed; boundary=gc0p4Jq0M2Yt08jU534c0p",
342
+ Some("gc0p4Jq0M2Yt08jU534c0p"),
343
+ ),
344
+ ("multipart/mixed", None),
345
+ ];
346
+
347
+ for (input, expected) in cases {
348
+ let mut headers = HeaderMap::new();
349
+ headers.insert(CONTENT_TYPE, HeaderValue::from_str(input).unwrap());
350
+
351
+ let actual = parse_multipart_boundary(&headers).expect("parse must success");
352
+
353
+ assert_eq!(actual, expected)
354
+ }
355
+ }
356
+ }