code_ownership 2.1.4 → 2.2.0

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 (505) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config +2 -2
  3. data/Cargo.lock +6 -59
  4. data/ext/cargo-vendor/codeowners-0.5.0/.cargo-checksum.json +1 -0
  5. data/ext/cargo-vendor/codeowners-0.5.0/.github/workflows/audit.yml +31 -0
  6. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/.github/workflows/ci.yml +11 -0
  7. data/ext/cargo-vendor/codeowners-0.5.0/.github/workflows/codeql.yml +21 -0
  8. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/Cargo.lock +27 -115
  9. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/Cargo.toml +44 -3
  10. data/ext/cargo-vendor/codeowners-0.5.0/perf/README.md +204 -0
  11. data/ext/cargo-vendor/codeowners-0.5.0/perf/compare.sh +23 -0
  12. data/ext/cargo-vendor/codeowners-0.5.0/perf/run.sh +28 -0
  13. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/rust-toolchain.toml +1 -1
  14. data/ext/cargo-vendor/codeowners-0.5.0/src/bin/codeowners-perf.rs +719 -0
  15. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/cache/file.rs +9 -9
  16. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/cache/mod.rs +4 -4
  17. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/cache/noop.rs +4 -4
  18. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/cli.rs +7 -7
  19. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/main.rs +3 -3
  20. data/ext/cargo-vendor/codeowners-0.5.0/src/ownership/file_owner_resolver.rs +829 -0
  21. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/validator.rs +108 -15
  22. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership.rs +22 -3
  23. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/project.rs +4 -4
  24. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/project_builder.rs +40 -14
  25. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/project_file_builder.rs +2 -2
  26. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/runner/api.rs +8 -5
  27. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/runner/types.rs +1 -2
  28. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/runner.rs +39 -29
  29. data/ext/cargo-vendor/codeowners-0.5.0/tests/annotation_in_unowned_team_glob_test.rs +64 -0
  30. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/common/mod.rs +1 -1
  31. data/ext/cargo-vendor/codeowners-0.5.0/tests/directory_codeowner_github_team_test.rs +22 -0
  32. data/ext/cargo-vendor/codeowners-0.5.0/tests/empty_directory_codeowner_test.rs +26 -0
  33. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/.github/CODEOWNERS +18 -0
  34. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/config/code_ownership.yml +4 -0
  35. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/config/teams/alpha.yml +7 -0
  36. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/config/teams/beta.yml +3 -0
  37. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/ruby/app/services/alpha_owned.rb +2 -0
  38. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/annotation_in_unowned_team_glob/ruby/app/services/beta_owned.rb +4 -0
  39. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team/.github/CODEOWNERS +15 -0
  40. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team/app/by_handle/.codeowner +1 -0
  41. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team/app/by_handle/handled.rb +2 -0
  42. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team/app/by_name/named.rb +2 -0
  43. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/.github/CODEOWNERS +14 -0
  44. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/app/services/.codeowner +1 -0
  45. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/app/services/nested/.codeowner +1 -0
  46. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/app/services/nested/nested_file.rb +2 -0
  47. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/config/code_ownership.yml +10 -0
  48. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/empty-directory-codeowner/config/teams/foo.yml +5 -0
  49. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/.github/CODEOWNERS +14 -0
  50. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/app/services/.codeowner +1 -0
  51. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/app/services/nested/.codeowner +1 -0
  52. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/app/services/nested/nested_file.rb +2 -0
  53. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/config/code_ownership.yml +10 -0
  54. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/invalid-directory-codeowner/config/teams/foo.yml +5 -0
  55. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/multiple-directory-owners/app/services/.codeowner +1 -0
  56. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/multiple-directory-owners/config/code_ownership.yml +10 -0
  57. data/ext/cargo-vendor/codeowners-0.5.0/tests/fixtures/multiple-directory-owners/config/teams/foo.yml +5 -0
  58. data/ext/cargo-vendor/codeowners-0.5.0/tests/global_gitignore_test.rs +50 -0
  59. data/ext/cargo-vendor/codeowners-0.5.0/tests/invalid_directory_codeowner_test.rs +26 -0
  60. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/invalid_project_test.rs +9 -9
  61. data/ext/cargo-vendor/codeowners-0.5.0/tests/perf_harness_test.rs +245 -0
  62. data/ext/cargo-vendor/codeowners-0.5.0/tests/untracked_new_file_test.rs +63 -0
  63. data/ext/cargo-vendor/codeowners-0.5.0/tests/untracked_source_file_test.rs +40 -0
  64. data/ext/cargo-vendor/error-stack-0.8.0/.cargo-checksum.json +1 -0
  65. data/ext/cargo-vendor/error-stack-0.8.0/.cargo_vcs_info.json +6 -0
  66. data/ext/cargo-vendor/error-stack-0.8.0/.justfile +16 -0
  67. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/CHANGELOG.md +50 -1
  68. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/Cargo.lock +253 -310
  69. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/Cargo.toml +107 -52
  70. data/ext/cargo-vendor/error-stack-0.8.0/Cargo.toml.orig +109 -0
  71. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/README.md +16 -18
  72. data/ext/cargo-vendor/error-stack-0.8.0/build.rs +28 -0
  73. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/examples/demo.rs +21 -19
  74. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/examples/detect.rs +6 -6
  75. data/ext/cargo-vendor/error-stack-0.8.0/examples/exit_code.rs +25 -0
  76. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/examples/parse_config.rs +5 -5
  77. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/compat/anyhow.rs +7 -7
  78. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/compat/eyre.rs +7 -6
  79. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/compat/mod.rs +7 -9
  80. data/ext/cargo-vendor/error-stack-0.8.0/src/context.rs +52 -0
  81. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/error.rs +2 -9
  82. data/ext/cargo-vendor/error-stack-0.8.0/src/ext/iter.rs +286 -0
  83. data/ext/cargo-vendor/error-stack-0.8.0/src/ext/mod.rs +19 -0
  84. data/ext/cargo-vendor/error-stack-0.8.0/src/ext/stream.rs +212 -0
  85. data/ext/cargo-vendor/error-stack-0.8.0/src/ext/tuple.rs +218 -0
  86. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/charset.rs +12 -12
  87. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/color.rs +30 -30
  88. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/config.rs +1 -1
  89. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/hook.rs +23 -24
  90. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/location.rs +3 -3
  91. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/mod.rs +62 -52
  92. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/frame/frame_impl.rs +12 -15
  93. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/frame/kind.rs +11 -10
  94. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/frame/mod.rs +8 -10
  95. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/future.rs +57 -63
  96. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/hook/context.rs +18 -20
  97. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/hook/mod.rs +16 -15
  98. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/iter.rs +12 -57
  99. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/lib.rs +99 -87
  100. data/ext/cargo-vendor/error-stack-0.8.0/src/macros.rs +212 -0
  101. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/report.rs +525 -207
  102. data/ext/cargo-vendor/error-stack-0.8.0/src/result.rs +137 -0
  103. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/serde.rs +53 -38
  104. data/ext/cargo-vendor/error-stack-0.8.0/src/sink.rs +672 -0
  105. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/common.rs +36 -24
  106. data/ext/cargo-vendor/error-stack-0.8.0/tests/compiletest.rs +22 -0
  107. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__charset_ascii.snap +1 -1
  108. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__charset_utf8.snap +1 -1
  109. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__diagnostics_add.snap +1 -1
  110. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__doc.snap +1 -1
  111. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__emit.snap +1 -1
  112. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__emit_alt.snap +1 -1
  113. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__hookcontext_cast.snap +1 -1
  114. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__hookcontext_decrement.snap +1 -1
  115. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__hookcontext_emit.snap +1 -1
  116. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__hookcontext_increment.snap +1 -1
  117. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__hookcontext_storage.snap +1 -1
  118. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__preference_color.snap +1 -1
  119. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__preference_emphasis.snap +1 -1
  120. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt__preference_none.snap +1 -1
  121. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/fmt_doc_alt.snap +1 -1
  122. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/hook__debug_hook.snap +1 -1
  123. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/hook__debug_hook_provide.snap +1 -1
  124. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/lib__suggestion.snap +2 -2
  125. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/report_debug__doc.snap +3 -3
  126. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__complex.snap +1 -1
  127. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_location.snap +1 -1
  128. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__linear.snap +2 -2
  129. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__linear_ext.snap +2 -2
  130. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__multiline_context.snap +3 -3
  131. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__sources.snap +1 -1
  132. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__sources_transparent.snap +1 -1
  133. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__sources_nested.snap +10 -10
  134. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__sources_nested@spantrace-backtrace.snap +10 -10
  135. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__sources_nested_alternate.snap +10 -10
  136. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__sources_nested_alternate@spantrace-backtrace.snap +10 -10
  137. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_serialize__attachment.snap +1 -1
  138. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_serialize__context.snap +1 -1
  139. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_serialize__multiple_sources.snap +2 -2
  140. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_serialize__multiple_sources_at_root.snap +2 -2
  141. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_attach.rs +41 -15
  142. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_attach_printable.rs +14 -15
  143. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_backtrace.rs +0 -1
  144. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_change_context.rs +31 -9
  145. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_compatibility.rs +8 -17
  146. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_conversion.rs +25 -3
  147. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_debug.rs +91 -91
  148. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_display.rs +8 -9
  149. data/ext/cargo-vendor/error-stack-0.8.0/tests/test_downcast.rs +101 -0
  150. data/ext/cargo-vendor/error-stack-0.8.0/tests/test_extend.rs +99 -0
  151. data/ext/cargo-vendor/error-stack-0.8.0/tests/test_frame.rs +136 -0
  152. data/ext/cargo-vendor/error-stack-0.8.0/tests/test_iter.rs +132 -0
  153. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_macros.rs +5 -31
  154. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_provision.rs +3 -2
  155. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_serialize.rs +14 -14
  156. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/test_span_trace.rs +10 -11
  157. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/attach_diagnostics.rs +21 -0
  158. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/attach_diagnostics.stderr +23 -0
  159. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/frames_mut_escape.rs +28 -0
  160. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/frames_mut_escape.stderr +13 -0
  161. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/macro_invalid_args.rs +32 -0
  162. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/macro_invalid_args.stderr +132 -0
  163. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/missing_args.rs +32 -0
  164. data/ext/cargo-vendor/error-stack-0.8.0/tests/ui/missing_args.stderr +35 -0
  165. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/ui/must_use.rs +3 -3
  166. data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/ui/must_use.stderr +1 -1
  167. data/ext/code_ownership/Cargo.toml +1 -1
  168. data/ext/code_ownership/src/lib.rs +13 -1
  169. data/lib/code_ownership/version.rb +1 -1
  170. data/lib/code_ownership.rb +3 -0
  171. metadata +340 -431
  172. data/ext/cargo-vendor/ahash-0.7.8/.cargo-checksum.json +0 -1
  173. data/ext/cargo-vendor/ahash-0.7.8/.cargo_vcs_info.json +0 -6
  174. data/ext/cargo-vendor/ahash-0.7.8/.github/workflows/rust.yml +0 -151
  175. data/ext/cargo-vendor/ahash-0.7.8/Cargo.toml +0 -149
  176. data/ext/cargo-vendor/ahash-0.7.8/Cargo.toml.orig +0 -96
  177. data/ext/cargo-vendor/ahash-0.7.8/FAQ.md +0 -118
  178. data/ext/cargo-vendor/ahash-0.7.8/LICENSE-APACHE +0 -201
  179. data/ext/cargo-vendor/ahash-0.7.8/LICENSE-MIT +0 -25
  180. data/ext/cargo-vendor/ahash-0.7.8/README.md +0 -110
  181. data/ext/cargo-vendor/ahash-0.7.8/build.rs +0 -47
  182. data/ext/cargo-vendor/ahash-0.7.8/rustfmt.toml +0 -1
  183. data/ext/cargo-vendor/ahash-0.7.8/src/aes_hash.rs +0 -440
  184. data/ext/cargo-vendor/ahash-0.7.8/src/convert.rs +0 -167
  185. data/ext/cargo-vendor/ahash-0.7.8/src/fallback_hash.rs +0 -392
  186. data/ext/cargo-vendor/ahash-0.7.8/src/hash_map.rs +0 -371
  187. data/ext/cargo-vendor/ahash-0.7.8/src/hash_quality_test.rs +0 -517
  188. data/ext/cargo-vendor/ahash-0.7.8/src/hash_set.rs +0 -313
  189. data/ext/cargo-vendor/ahash-0.7.8/src/lib.rs +0 -263
  190. data/ext/cargo-vendor/ahash-0.7.8/src/operations.rs +0 -330
  191. data/ext/cargo-vendor/ahash-0.7.8/src/random_state.rs +0 -363
  192. data/ext/cargo-vendor/ahash-0.7.8/src/specialize.rs +0 -239
  193. data/ext/cargo-vendor/ahash-0.7.8/tests/bench.rs +0 -154
  194. data/ext/cargo-vendor/ahash-0.7.8/tests/map_tests.rs +0 -203
  195. data/ext/cargo-vendor/ahash-0.7.8/tests/nopanic.rs +0 -72
  196. data/ext/cargo-vendor/codeowners-0.3.3/.cargo-checksum.json +0 -1
  197. data/ext/cargo-vendor/codeowners-0.3.3/.github/workflows/audit.yml +0 -19
  198. data/ext/cargo-vendor/codeowners-0.3.3/src/ownership/file_owner_resolver.rs +0 -416
  199. data/ext/cargo-vendor/error-stack-0.5.0/.cargo-checksum.json +0 -1
  200. data/ext/cargo-vendor/error-stack-0.5.0/.cargo_vcs_info.json +0 -6
  201. data/ext/cargo-vendor/error-stack-0.5.0/.justfile +0 -58
  202. data/ext/cargo-vendor/error-stack-0.5.0/Cargo.toml.orig +0 -87
  203. data/ext/cargo-vendor/error-stack-0.5.0/build.rs +0 -29
  204. data/ext/cargo-vendor/error-stack-0.5.0/examples/exit_code.rs +0 -24
  205. data/ext/cargo-vendor/error-stack-0.5.0/rust-toolchain.toml +0 -4
  206. data/ext/cargo-vendor/error-stack-0.5.0/src/context.rs +0 -132
  207. data/ext/cargo-vendor/error-stack-0.5.0/src/macros.rs +0 -253
  208. data/ext/cargo-vendor/error-stack-0.5.0/src/result.rs +0 -267
  209. data/ext/cargo-vendor/error-stack-0.5.0/tests/compiletest.rs +0 -7
  210. data/ext/cargo-vendor/error-stack-0.5.0/tests/snapshots/test_debug__sources_nested@backtrace.snap +0 -104
  211. data/ext/cargo-vendor/error-stack-0.5.0/tests/snapshots/test_debug__sources_nested@spantrace.snap +0 -104
  212. data/ext/cargo-vendor/error-stack-0.5.0/tests/snapshots/test_debug__sources_nested_alternate@backtrace.snap +0 -104
  213. data/ext/cargo-vendor/error-stack-0.5.0/tests/snapshots/test_debug__sources_nested_alternate@spantrace.snap +0 -104
  214. data/ext/cargo-vendor/error-stack-0.5.0/tests/test_downcast.rs +0 -41
  215. data/ext/cargo-vendor/error-stack-0.5.0/tests/test_extend.rs +0 -78
  216. data/ext/cargo-vendor/error-stack-0.5.0/tests/test_frame.rs +0 -126
  217. data/ext/cargo-vendor/error-stack-0.5.0/tests/test_iter.rs +0 -99
  218. data/ext/cargo-vendor/error-stack-0.5.0/tests/ui/macro_invalid_args.rs +0 -60
  219. data/ext/cargo-vendor/error-stack-0.5.0/tests/ui/macro_invalid_args.stderr +0 -101
  220. data/ext/cargo-vendor/getrandom-0.2.16/.cargo-checksum.json +0 -1
  221. data/ext/cargo-vendor/getrandom-0.2.16/.cargo_vcs_info.json +0 -6
  222. data/ext/cargo-vendor/getrandom-0.2.16/CHANGELOG.md +0 -498
  223. data/ext/cargo-vendor/getrandom-0.2.16/Cargo.lock +0 -354
  224. data/ext/cargo-vendor/getrandom-0.2.16/Cargo.toml +0 -121
  225. data/ext/cargo-vendor/getrandom-0.2.16/Cargo.toml.orig +0 -67
  226. data/ext/cargo-vendor/getrandom-0.2.16/LICENSE-APACHE +0 -201
  227. data/ext/cargo-vendor/getrandom-0.2.16/LICENSE-MIT +0 -26
  228. data/ext/cargo-vendor/getrandom-0.2.16/README.md +0 -81
  229. data/ext/cargo-vendor/getrandom-0.2.16/SECURITY.md +0 -13
  230. data/ext/cargo-vendor/getrandom-0.2.16/benches/buffer.rs +0 -71
  231. data/ext/cargo-vendor/getrandom-0.2.16/src/apple-other.rs +0 -24
  232. data/ext/cargo-vendor/getrandom-0.2.16/src/custom.rs +0 -105
  233. data/ext/cargo-vendor/getrandom-0.2.16/src/error.rs +0 -189
  234. data/ext/cargo-vendor/getrandom-0.2.16/src/error_impls.rs +0 -15
  235. data/ext/cargo-vendor/getrandom-0.2.16/src/espidf.rs +0 -18
  236. data/ext/cargo-vendor/getrandom-0.2.16/src/fuchsia.rs +0 -13
  237. data/ext/cargo-vendor/getrandom-0.2.16/src/getentropy.rs +0 -21
  238. data/ext/cargo-vendor/getrandom-0.2.16/src/getrandom.rs +0 -25
  239. data/ext/cargo-vendor/getrandom-0.2.16/src/hermit.rs +0 -29
  240. data/ext/cargo-vendor/getrandom-0.2.16/src/js.rs +0 -155
  241. data/ext/cargo-vendor/getrandom-0.2.16/src/lazy.rs +0 -56
  242. data/ext/cargo-vendor/getrandom-0.2.16/src/lib.rs +0 -407
  243. data/ext/cargo-vendor/getrandom-0.2.16/src/linux_android.rs +0 -7
  244. data/ext/cargo-vendor/getrandom-0.2.16/src/linux_android_with_fallback.rs +0 -33
  245. data/ext/cargo-vendor/getrandom-0.2.16/src/netbsd.rs +0 -46
  246. data/ext/cargo-vendor/getrandom-0.2.16/src/rdrand.rs +0 -121
  247. data/ext/cargo-vendor/getrandom-0.2.16/src/solaris.rs +0 -34
  248. data/ext/cargo-vendor/getrandom-0.2.16/src/solid.rs +0 -18
  249. data/ext/cargo-vendor/getrandom-0.2.16/src/use_file.rs +0 -120
  250. data/ext/cargo-vendor/getrandom-0.2.16/src/util.rs +0 -35
  251. data/ext/cargo-vendor/getrandom-0.2.16/src/util_libc.rs +0 -162
  252. data/ext/cargo-vendor/getrandom-0.2.16/src/vxworks.rs +0 -29
  253. data/ext/cargo-vendor/getrandom-0.2.16/src/wasi.rs +0 -17
  254. data/ext/cargo-vendor/getrandom-0.2.16/src/windows.rs +0 -59
  255. data/ext/cargo-vendor/getrandom-0.2.16/tests/common/mod.rs +0 -100
  256. data/ext/cargo-vendor/getrandom-0.2.16/tests/custom.rs +0 -54
  257. data/ext/cargo-vendor/getrandom-0.2.16/tests/normal.rs +0 -11
  258. data/ext/cargo-vendor/getrandom-0.2.16/tests/rdrand.rs +0 -22
  259. data/ext/cargo-vendor/hashbrown-0.12.3/.cargo-checksum.json +0 -1
  260. data/ext/cargo-vendor/hashbrown-0.12.3/.cargo_vcs_info.json +0 -6
  261. data/ext/cargo-vendor/hashbrown-0.12.3/CHANGELOG.md +0 -402
  262. data/ext/cargo-vendor/hashbrown-0.12.3/Cargo.toml +0 -113
  263. data/ext/cargo-vendor/hashbrown-0.12.3/Cargo.toml.orig +0 -60
  264. data/ext/cargo-vendor/hashbrown-0.12.3/LICENSE-APACHE +0 -201
  265. data/ext/cargo-vendor/hashbrown-0.12.3/LICENSE-MIT +0 -25
  266. data/ext/cargo-vendor/hashbrown-0.12.3/README.md +0 -126
  267. data/ext/cargo-vendor/hashbrown-0.12.3/benches/bench.rs +0 -331
  268. data/ext/cargo-vendor/hashbrown-0.12.3/benches/insert_unique_unchecked.rs +0 -32
  269. data/ext/cargo-vendor/hashbrown-0.12.3/clippy.toml +0 -1
  270. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/mod.rs +0 -4
  271. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/rayon/helpers.rs +0 -27
  272. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/rayon/map.rs +0 -734
  273. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/rayon/mod.rs +0 -4
  274. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/rayon/raw.rs +0 -231
  275. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/rayon/set.rs +0 -659
  276. data/ext/cargo-vendor/hashbrown-0.12.3/src/external_trait_impls/serde.rs +0 -201
  277. data/ext/cargo-vendor/hashbrown-0.12.3/src/lib.rs +0 -150
  278. data/ext/cargo-vendor/hashbrown-0.12.3/src/macros.rs +0 -70
  279. data/ext/cargo-vendor/hashbrown-0.12.3/src/map.rs +0 -8408
  280. data/ext/cargo-vendor/hashbrown-0.12.3/src/raw/alloc.rs +0 -73
  281. data/ext/cargo-vendor/hashbrown-0.12.3/src/raw/bitmask.rs +0 -122
  282. data/ext/cargo-vendor/hashbrown-0.12.3/src/raw/generic.rs +0 -154
  283. data/ext/cargo-vendor/hashbrown-0.12.3/src/raw/mod.rs +0 -2460
  284. data/ext/cargo-vendor/hashbrown-0.12.3/src/raw/sse2.rs +0 -146
  285. data/ext/cargo-vendor/hashbrown-0.12.3/src/rustc_entry.rs +0 -630
  286. data/ext/cargo-vendor/hashbrown-0.12.3/src/scopeguard.rs +0 -74
  287. data/ext/cargo-vendor/hashbrown-0.12.3/src/set.rs +0 -2790
  288. data/ext/cargo-vendor/hashbrown-0.12.3/tests/hasher.rs +0 -65
  289. data/ext/cargo-vendor/hashbrown-0.12.3/tests/rayon.rs +0 -533
  290. data/ext/cargo-vendor/hashbrown-0.12.3/tests/serde.rs +0 -65
  291. data/ext/cargo-vendor/hashbrown-0.12.3/tests/set.rs +0 -34
  292. data/ext/cargo-vendor/lru-0.7.8/.cargo-checksum.json +0 -1
  293. data/ext/cargo-vendor/lru-0.7.8/.cargo_vcs_info.json +0 -6
  294. data/ext/cargo-vendor/lru-0.7.8/.github/workflows/main.yml +0 -54
  295. data/ext/cargo-vendor/lru-0.7.8/CHANGELOG.md +0 -194
  296. data/ext/cargo-vendor/lru-0.7.8/Cargo.toml +0 -42
  297. data/ext/cargo-vendor/lru-0.7.8/Cargo.toml.orig +0 -22
  298. data/ext/cargo-vendor/lru-0.7.8/LICENSE +0 -21
  299. data/ext/cargo-vendor/lru-0.7.8/README.md +0 -62
  300. data/ext/cargo-vendor/lru-0.7.8/src/lib.rs +0 -1872
  301. data/ext/cargo-vendor/version_check-0.9.5/.cargo-checksum.json +0 -1
  302. data/ext/cargo-vendor/version_check-0.9.5/.cargo_vcs_info.json +0 -6
  303. data/ext/cargo-vendor/version_check-0.9.5/.github/workflows/ci.yml +0 -42
  304. data/ext/cargo-vendor/version_check-0.9.5/.travis.yml +0 -6
  305. data/ext/cargo-vendor/version_check-0.9.5/Cargo.toml +0 -38
  306. data/ext/cargo-vendor/version_check-0.9.5/Cargo.toml.orig +0 -13
  307. data/ext/cargo-vendor/version_check-0.9.5/LICENSE-APACHE +0 -201
  308. data/ext/cargo-vendor/version_check-0.9.5/LICENSE-MIT +0 -19
  309. data/ext/cargo-vendor/version_check-0.9.5/README.md +0 -80
  310. data/ext/cargo-vendor/version_check-0.9.5/src/channel.rs +0 -195
  311. data/ext/cargo-vendor/version_check-0.9.5/src/date.rs +0 -203
  312. data/ext/cargo-vendor/version_check-0.9.5/src/lib.rs +0 -528
  313. data/ext/cargo-vendor/version_check-0.9.5/src/version.rs +0 -316
  314. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/.cargo-checksum.json +0 -1
  315. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/.cargo_vcs_info.json +0 -6
  316. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/.github/workflows/main.yml +0 -44
  317. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/.gitmodules +0 -3
  318. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/CODE_OF_CONDUCT.md +0 -49
  319. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/CONTRIBUTING.md +0 -8
  320. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/Cargo.lock +0 -23
  321. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/Cargo.toml +0 -59
  322. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/Cargo.toml.orig +0 -29
  323. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-APACHE +0 -201
  324. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-Apache-2.0_WITH_LLVM-exception +0 -220
  325. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/LICENSE-MIT +0 -23
  326. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/ORG_CODE_OF_CONDUCT.md +0 -143
  327. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/README.md +0 -94
  328. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/SECURITY.md +0 -29
  329. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/src/lib.rs +0 -47
  330. data/ext/cargo-vendor/wasi-0.11.1+wasi-snapshot-preview1/src/lib_generated.rs +0 -2366
  331. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/.github/CODEOWNERS +0 -0
  332. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/.github/workflows/dotslash-config.json +0 -0
  333. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/.rustfmt.toml +0 -0
  334. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/.rusty-hook.toml +0 -0
  335. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/AGENTS.md +0 -0
  336. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/CLAUDE.md +0 -0
  337. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/README.md +0 -0
  338. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/dev/run_benchmarks_for_file.sh +0 -0
  339. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/dev/run_benchmarks_for_gv.sh +0 -0
  340. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/common_test.rs +0 -0
  341. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/config.rs +0 -0
  342. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/crosscheck.rs +0 -0
  343. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/lib.rs +0 -0
  344. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/codeowners_file_parser.rs +0 -0
  345. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/codeowners_query.rs +0 -0
  346. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/file_generator.rs +0 -0
  347. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/file_owner_finder.rs +0 -0
  348. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/annotated_file_mapper.rs +0 -0
  349. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/directory_mapper.rs +0 -0
  350. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/escaper.rs +0 -0
  351. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/package_mapper.rs +0 -0
  352. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/team_gem_mapper.rs +0 -0
  353. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/team_glob_mapper.rs +0 -0
  354. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper/team_yml_mapper.rs +0 -0
  355. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/ownership/mapper.rs +0 -0
  356. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/path_utils.rs +0 -0
  357. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/src/tracked_files.rs +0 -0
  358. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/cache_test.rs +0 -0
  359. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/codeowners_path_test.rs +0 -0
  360. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/crosscheck_owners_test.rs +0 -0
  361. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/executable_name_config_test.rs +10 -10
  362. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_codeowners_path/config/code_ownership.yml +0 -0
  363. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_codeowners_path/config/teams/test_team.yml +0 -0
  364. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_codeowners_path/docs/CODEOWNERS +3 -3
  365. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_codeowners_path/expected/CODEOWNERS +3 -3
  366. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_codeowners_path/ruby/app/models/test.rb +0 -0
  367. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/.github/CODEOWNERS +0 -0
  368. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/app/foo.rb +0 -0
  369. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/config/code_ownership.yml +0 -0
  370. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/config/teams/foo.yml +0 -0
  371. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/config/teams/payments.yml +0 -0
  372. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/custom_executable_name/ruby/app/payments/foo.rb +0 -0
  373. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/default_executable_name/.github/CODEOWNERS +0 -0
  374. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/default_executable_name/app/bar.rb +0 -0
  375. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/default_executable_name/config/code_ownership.yml +0 -0
  376. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/default_executable_name/config/teams/bar.yml +0 -0
  377. data/ext/cargo-vendor/{codeowners-0.3.3/tests/fixtures/multiple-directory-owners/app/services → codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team/app/by_name}/.codeowner +0 -0
  378. data/ext/cargo-vendor/{codeowners-0.3.3/tests/fixtures/multiple-directory-owners → codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team}/config/code_ownership.yml +0 -0
  379. data/ext/cargo-vendor/{codeowners-0.3.3/tests/fixtures/multiple-directory-owners → codeowners-0.5.0/tests/fixtures/directory-codeowner-github-team}/config/teams/foo.yml +0 -0
  380. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/.github/CODEOWNERS +0 -0
  381. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/config/code_ownership.yml +0 -0
  382. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/config/teams/payments.yml +0 -0
  383. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/config/teams/payroll.yml +0 -0
  384. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/gems/payroll_calculator/calculator.rb +0 -0
  385. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/models/bank_account.rb +0 -0
  386. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/models/blockchain.rb +0 -0
  387. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/models/payroll.rb +0 -0
  388. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/payments/nacha.rb +0 -0
  389. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/services/.codeowner +0 -0
  390. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/services/multi_owned.rb +0 -0
  391. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/app/unowned.rb +0 -0
  392. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/invalid_project/ruby/packages/payroll_flow/package.yml +0 -0
  393. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/.github/CODEOWNERS +0 -0
  394. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/.keep +0 -0
  395. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/config/code_ownership.yml +0 -0
  396. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/config/teams/design.yml +0 -0
  397. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/config/teams/frontend.yml +0 -0
  398. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/frontend/apps/public/index.tsx +0 -0
  399. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/frontend/packages/dashboard/package.json +0 -0
  400. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/frontend/packages/dashboard/src/index.tsx +0 -0
  401. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/frontend/packages/ui-kit/.codeowner +0 -0
  402. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/javascript_only_project/frontend/packages/ui-kit/src/button.tsx +0 -0
  403. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/missing_github_team/.github/CODEOWNERS +0 -0
  404. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/missing_github_team/config/code_ownership.yml +0 -0
  405. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/missing_github_team/config/teams/bad_team.yml +0 -0
  406. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/missing_github_team/config/teams/good.yml +0 -0
  407. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/missing_github_team/gems/pets/dog.rb +0 -0
  408. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/.github/CODEOWNERS +0 -0
  409. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/app/consumers/.codeowner +0 -0
  410. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/app/consumers/deep/nesting/nestdir/deep_file.rb +0 -0
  411. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/app/consumers/one_owner.rb +0 -0
  412. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/app/services/exciting/.codeowner +0 -0
  413. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/app/services/exciting/some_other_file.rb +0 -0
  414. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/multiple-directory-owners/config/teams/bar.yml +0 -0
  415. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/.github/CODEOWNERS +9 -9
  416. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/.ignore +0 -0
  417. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/config/code_ownership.yml +0 -0
  418. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/config/teams/payments.yml +0 -0
  419. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/config/teams/payroll.yml +0 -0
  420. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/config/teams/ux.yml +0 -0
  421. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/gems/payroll_calculator/calculator.rb +0 -0
  422. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/gems/pets/dog.rb +0 -0
  423. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/PayrollFlow/index.tsx +0 -0
  424. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/PayrollFlow/package.json +0 -0
  425. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/items/(special)/.codeowner +0 -0
  426. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/items/(special)/pay.ts +0 -0
  427. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/items/.codeowner +0 -0
  428. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/items/item.ts +0 -0
  429. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/javascript/packages/list/page-admin.tsx +0 -0
  430. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/models/bank_account.rb +0 -0
  431. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/models/payroll.rb +0 -0
  432. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/payments/foo/.codeowner +0 -0
  433. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/payments/foo/ownedby_payroll.rb +0 -0
  434. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/payments/nacha.rb +0 -0
  435. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/payroll/.codeowner +0 -0
  436. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/payroll/payroll.rb +0 -0
  437. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/views/foos/edit.erb +0 -0
  438. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/views/foos/index.html.erb +0 -0
  439. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/app/views/foos/new.html.erb +0 -0
  440. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/ignored_files/git_ignored.rb +0 -0
  441. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/ruby/packages/payroll_flow/package.yml +0 -0
  442. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project/should_be_ignored/an_ignored_file.rb +0 -0
  443. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/.github/CODEOWNERS +12 -12
  444. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/config/code_ownership.yml +0 -0
  445. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/config/teams/brewers.yml +0 -0
  446. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/config/teams/cubs.yml +0 -0
  447. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/config/teams/giants.yml +0 -0
  448. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/config/teams/rockies.yml +0 -0
  449. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/datepicker/package.json +0 -0
  450. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/datepicker/src/picks/dp.tsx +0 -0
  451. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/list/package.json +0 -0
  452. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/list/src/item.tsx +0 -0
  453. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/package.json +0 -0
  454. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/src/field.tsx +0 -0
  455. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/frontend/packages/components/textfield/src/fields/small.tsx +0 -0
  456. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/gems/apollo/lib/apollo.rb +0 -0
  457. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/gems/ivy/lib/ivy.rb +0 -0
  458. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/gems/lager/lib/lager.rb +0 -0
  459. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/gems/summit/lib/summit.rb +0 -0
  460. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/games/app/services/stats.rb +0 -0
  461. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/games/package.yml +0 -0
  462. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/locations/app/services/capacity.rb +0 -0
  463. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/locations/package.yml +0 -0
  464. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/schedule/app/services/date.rb +0 -0
  465. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/packs/schedule/package.yml +0 -0
  466. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/brewers/lib/util.rb +0 -0
  467. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/brewers/services/play.rb +0 -0
  468. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/.codeowner +0 -0
  469. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/.codeowner +0 -0
  470. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/db/price.rb +0 -0
  471. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/models/entertainment.rb +0 -0
  472. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/cubs/services/play.rb +0 -0
  473. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/giants/services/play.rb +0 -0
  474. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/fixtures/valid_project_with_overrides/ruby/app/rockies/services/play.rb +0 -0
  475. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/git_stage_test.rs +0 -0
  476. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/invalid_project_structure_test.rs +0 -0
  477. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/missing_github_team_test.rs +0 -0
  478. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/multiple_directory_owners_test.rs +0 -0
  479. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/run_config_executable_override_test.rs +0 -0
  480. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/runner_api.rs +0 -0
  481. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/untracked_files_test.rs +0 -0
  482. data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/valid_project_test.rs +6 -6
  483. /data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/valid_project_with_overrides_test.rs +0 -0
  484. /data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tests/validate_files_test.rs +0 -0
  485. /data/ext/cargo-vendor/{codeowners-0.3.3 → codeowners-0.5.0}/tmp/.gitkeep +0 -0
  486. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/LICENSE-APACHE.md +0 -0
  487. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/LICENSE-MIT.md +0 -0
  488. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/LICENSE.md +0 -0
  489. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/src/fmt/override.rs +0 -0
  490. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/hook__location_hook.snap +0 -0
  491. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/report_display__doc.snap +0 -0
  492. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/doc/report_display_alt__doc.snap +0 -0
  493. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__alt.snap +0 -0
  494. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__charset_ascii.snap +0 -0
  495. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__color_mode_color.snap +0 -0
  496. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__color_mode_emphasis.snap +0 -0
  497. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook.snap +0 -0
  498. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_context.snap +0 -0
  499. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_decr.snap +0 -0
  500. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_for_context.snap +0 -0
  501. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_incr.snap +0 -0
  502. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_multiple.snap +0 -0
  503. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__hook_provider.snap +0 -0
  504. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__multiline.snap +0 -0
  505. /data/ext/cargo-vendor/{error-stack-0.5.0 → error-stack-0.8.0}/tests/snapshots/test_debug__full__norm.snap +0 -0
@@ -1,2460 +0,0 @@
1
- use crate::alloc::alloc::{handle_alloc_error, Layout};
2
- use crate::scopeguard::{guard, ScopeGuard};
3
- use crate::TryReserveError;
4
- use core::iter::FusedIterator;
5
- use core::marker::PhantomData;
6
- use core::mem;
7
- use core::mem::ManuallyDrop;
8
- use core::mem::MaybeUninit;
9
- use core::ptr::NonNull;
10
- use core::{hint, ptr};
11
-
12
- cfg_if! {
13
- // Use the SSE2 implementation if possible: it allows us to scan 16 buckets
14
- // at once instead of 8. We don't bother with AVX since it would require
15
- // runtime dispatch and wouldn't gain us much anyways: the probability of
16
- // finding a match drops off drastically after the first few buckets.
17
- //
18
- // I attempted an implementation on ARM using NEON instructions, but it
19
- // turns out that most NEON instructions have multi-cycle latency, which in
20
- // the end outweighs any gains over the generic implementation.
21
- if #[cfg(all(
22
- target_feature = "sse2",
23
- any(target_arch = "x86", target_arch = "x86_64"),
24
- not(miri)
25
- ))] {
26
- mod sse2;
27
- use sse2 as imp;
28
- } else {
29
- #[path = "generic.rs"]
30
- mod generic;
31
- use generic as imp;
32
- }
33
- }
34
-
35
- mod alloc;
36
- pub(crate) use self::alloc::{do_alloc, Allocator, Global};
37
-
38
- mod bitmask;
39
-
40
- use self::bitmask::{BitMask, BitMaskIter};
41
- use self::imp::Group;
42
-
43
- // Branch prediction hint. This is currently only available on nightly but it
44
- // consistently improves performance by 10-15%.
45
- #[cfg(feature = "nightly")]
46
- use core::intrinsics::{likely, unlikely};
47
-
48
- // On stable we can use #[cold] to get a equivalent effect: this attributes
49
- // suggests that the function is unlikely to be called
50
- #[cfg(not(feature = "nightly"))]
51
- #[inline]
52
- #[cold]
53
- fn cold() {}
54
-
55
- #[cfg(not(feature = "nightly"))]
56
- #[inline]
57
- fn likely(b: bool) -> bool {
58
- if !b {
59
- cold();
60
- }
61
- b
62
- }
63
- #[cfg(not(feature = "nightly"))]
64
- #[inline]
65
- fn unlikely(b: bool) -> bool {
66
- if b {
67
- cold();
68
- }
69
- b
70
- }
71
-
72
- #[inline]
73
- unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
74
- to.offset_from(from) as usize
75
- }
76
-
77
- /// Whether memory allocation errors should return an error or abort.
78
- #[derive(Copy, Clone)]
79
- enum Fallibility {
80
- Fallible,
81
- Infallible,
82
- }
83
-
84
- impl Fallibility {
85
- /// Error to return on capacity overflow.
86
- #[cfg_attr(feature = "inline-more", inline)]
87
- fn capacity_overflow(self) -> TryReserveError {
88
- match self {
89
- Fallibility::Fallible => TryReserveError::CapacityOverflow,
90
- Fallibility::Infallible => panic!("Hash table capacity overflow"),
91
- }
92
- }
93
-
94
- /// Error to return on allocation error.
95
- #[cfg_attr(feature = "inline-more", inline)]
96
- fn alloc_err(self, layout: Layout) -> TryReserveError {
97
- match self {
98
- Fallibility::Fallible => TryReserveError::AllocError { layout },
99
- Fallibility::Infallible => handle_alloc_error(layout),
100
- }
101
- }
102
- }
103
-
104
- /// Control byte value for an empty bucket.
105
- const EMPTY: u8 = 0b1111_1111;
106
-
107
- /// Control byte value for a deleted bucket.
108
- const DELETED: u8 = 0b1000_0000;
109
-
110
- /// Checks whether a control byte represents a full bucket (top bit is clear).
111
- #[inline]
112
- fn is_full(ctrl: u8) -> bool {
113
- ctrl & 0x80 == 0
114
- }
115
-
116
- /// Checks whether a control byte represents a special value (top bit is set).
117
- #[inline]
118
- fn is_special(ctrl: u8) -> bool {
119
- ctrl & 0x80 != 0
120
- }
121
-
122
- /// Checks whether a special control value is EMPTY (just check 1 bit).
123
- #[inline]
124
- fn special_is_empty(ctrl: u8) -> bool {
125
- debug_assert!(is_special(ctrl));
126
- ctrl & 0x01 != 0
127
- }
128
-
129
- /// Primary hash function, used to select the initial bucket to probe from.
130
- #[inline]
131
- #[allow(clippy::cast_possible_truncation)]
132
- fn h1(hash: u64) -> usize {
133
- // On 32-bit platforms we simply ignore the higher hash bits.
134
- hash as usize
135
- }
136
-
137
- /// Secondary hash function, saved in the low 7 bits of the control byte.
138
- #[inline]
139
- #[allow(clippy::cast_possible_truncation)]
140
- fn h2(hash: u64) -> u8 {
141
- // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit
142
- // value, some hash functions (such as FxHash) produce a usize result
143
- // instead, which means that the top 32 bits are 0 on 32-bit platforms.
144
- let hash_len = usize::min(mem::size_of::<usize>(), mem::size_of::<u64>());
145
- let top7 = hash >> (hash_len * 8 - 7);
146
- (top7 & 0x7f) as u8 // truncation
147
- }
148
-
149
- /// Probe sequence based on triangular numbers, which is guaranteed (since our
150
- /// table size is a power of two) to visit every group of elements exactly once.
151
- ///
152
- /// A triangular probe has us jump by 1 more group every time. So first we
153
- /// jump by 1 group (meaning we just continue our linear scan), then 2 groups
154
- /// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on.
155
- ///
156
- /// Proof that the probe will visit every group in the table:
157
- /// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
158
- struct ProbeSeq {
159
- pos: usize,
160
- stride: usize,
161
- }
162
-
163
- impl ProbeSeq {
164
- #[inline]
165
- fn move_next(&mut self, bucket_mask: usize) {
166
- // We should have found an empty bucket by now and ended the probe.
167
- debug_assert!(
168
- self.stride <= bucket_mask,
169
- "Went past end of probe sequence"
170
- );
171
-
172
- self.stride += Group::WIDTH;
173
- self.pos += self.stride;
174
- self.pos &= bucket_mask;
175
- }
176
- }
177
-
178
- /// Returns the number of buckets needed to hold the given number of items,
179
- /// taking the maximum load factor into account.
180
- ///
181
- /// Returns `None` if an overflow occurs.
182
- // Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258
183
- #[cfg_attr(target_os = "emscripten", inline(never))]
184
- #[cfg_attr(not(target_os = "emscripten"), inline)]
185
- fn capacity_to_buckets(cap: usize) -> Option<usize> {
186
- debug_assert_ne!(cap, 0);
187
-
188
- // For small tables we require at least 1 empty bucket so that lookups are
189
- // guaranteed to terminate if an element doesn't exist in the table.
190
- if cap < 8 {
191
- // We don't bother with a table size of 2 buckets since that can only
192
- // hold a single element. Instead we skip directly to a 4 bucket table
193
- // which can hold 3 elements.
194
- return Some(if cap < 4 { 4 } else { 8 });
195
- }
196
-
197
- // Otherwise require 1/8 buckets to be empty (87.5% load)
198
- //
199
- // Be careful when modifying this, calculate_layout relies on the
200
- // overflow check here.
201
- let adjusted_cap = cap.checked_mul(8)? / 7;
202
-
203
- // Any overflows will have been caught by the checked_mul. Also, any
204
- // rounding errors from the division above will be cleaned up by
205
- // next_power_of_two (which can't overflow because of the previous division).
206
- Some(adjusted_cap.next_power_of_two())
207
- }
208
-
209
- /// Returns the maximum effective capacity for the given bucket mask, taking
210
- /// the maximum load factor into account.
211
- #[inline]
212
- fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
213
- if bucket_mask < 8 {
214
- // For tables with 1/2/4/8 buckets, we always reserve one empty slot.
215
- // Keep in mind that the bucket mask is one less than the bucket count.
216
- bucket_mask
217
- } else {
218
- // For larger tables we reserve 12.5% of the slots as empty.
219
- ((bucket_mask + 1) / 8) * 7
220
- }
221
- }
222
-
223
- /// Helper which allows the max calculation for ctrl_align to be statically computed for each T
224
- /// while keeping the rest of `calculate_layout_for` independent of `T`
225
- #[derive(Copy, Clone)]
226
- struct TableLayout {
227
- size: usize,
228
- ctrl_align: usize,
229
- }
230
-
231
- impl TableLayout {
232
- #[inline]
233
- fn new<T>() -> Self {
234
- let layout = Layout::new::<T>();
235
- Self {
236
- size: layout.size(),
237
- ctrl_align: usize::max(layout.align(), Group::WIDTH),
238
- }
239
- }
240
-
241
- #[inline]
242
- fn calculate_layout_for(self, buckets: usize) -> Option<(Layout, usize)> {
243
- debug_assert!(buckets.is_power_of_two());
244
-
245
- let TableLayout { size, ctrl_align } = self;
246
- // Manual layout calculation since Layout methods are not yet stable.
247
- let ctrl_offset =
248
- size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1);
249
- let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?;
250
-
251
- Some((
252
- unsafe { Layout::from_size_align_unchecked(len, ctrl_align) },
253
- ctrl_offset,
254
- ))
255
- }
256
- }
257
-
258
- /// Returns a Layout which describes the allocation required for a hash table,
259
- /// and the offset of the control bytes in the allocation.
260
- /// (the offset is also one past last element of buckets)
261
- ///
262
- /// Returns `None` if an overflow occurs.
263
- #[cfg_attr(feature = "inline-more", inline)]
264
- fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
265
- TableLayout::new::<T>().calculate_layout_for(buckets)
266
- }
267
-
268
- /// A reference to a hash table bucket containing a `T`.
269
- ///
270
- /// This is usually just a pointer to the element itself. However if the element
271
- /// is a ZST, then we instead track the index of the element in the table so
272
- /// that `erase` works properly.
273
- pub struct Bucket<T> {
274
- // Actually it is pointer to next element than element itself
275
- // this is needed to maintain pointer arithmetic invariants
276
- // keeping direct pointer to element introduces difficulty.
277
- // Using `NonNull` for variance and niche layout
278
- ptr: NonNull<T>,
279
- }
280
-
281
- // This Send impl is needed for rayon support. This is safe since Bucket is
282
- // never exposed in a public API.
283
- unsafe impl<T> Send for Bucket<T> {}
284
-
285
- impl<T> Clone for Bucket<T> {
286
- #[inline]
287
- fn clone(&self) -> Self {
288
- Self { ptr: self.ptr }
289
- }
290
- }
291
-
292
- impl<T> Bucket<T> {
293
- #[inline]
294
- unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self {
295
- let ptr = if mem::size_of::<T>() == 0 {
296
- // won't overflow because index must be less than length
297
- (index + 1) as *mut T
298
- } else {
299
- base.as_ptr().sub(index)
300
- };
301
- Self {
302
- ptr: NonNull::new_unchecked(ptr),
303
- }
304
- }
305
- #[inline]
306
- unsafe fn to_base_index(&self, base: NonNull<T>) -> usize {
307
- if mem::size_of::<T>() == 0 {
308
- self.ptr.as_ptr() as usize - 1
309
- } else {
310
- offset_from(base.as_ptr(), self.ptr.as_ptr())
311
- }
312
- }
313
- #[inline]
314
- pub fn as_ptr(&self) -> *mut T {
315
- if mem::size_of::<T>() == 0 {
316
- // Just return an arbitrary ZST pointer which is properly aligned
317
- mem::align_of::<T>() as *mut T
318
- } else {
319
- unsafe { self.ptr.as_ptr().sub(1) }
320
- }
321
- }
322
- #[inline]
323
- unsafe fn next_n(&self, offset: usize) -> Self {
324
- let ptr = if mem::size_of::<T>() == 0 {
325
- (self.ptr.as_ptr() as usize + offset) as *mut T
326
- } else {
327
- self.ptr.as_ptr().sub(offset)
328
- };
329
- Self {
330
- ptr: NonNull::new_unchecked(ptr),
331
- }
332
- }
333
- #[cfg_attr(feature = "inline-more", inline)]
334
- pub unsafe fn drop(&self) {
335
- self.as_ptr().drop_in_place();
336
- }
337
- #[inline]
338
- pub unsafe fn read(&self) -> T {
339
- self.as_ptr().read()
340
- }
341
- #[inline]
342
- pub unsafe fn write(&self, val: T) {
343
- self.as_ptr().write(val);
344
- }
345
- #[inline]
346
- pub unsafe fn as_ref<'a>(&self) -> &'a T {
347
- &*self.as_ptr()
348
- }
349
- #[inline]
350
- pub unsafe fn as_mut<'a>(&self) -> &'a mut T {
351
- &mut *self.as_ptr()
352
- }
353
- #[cfg(feature = "raw")]
354
- #[inline]
355
- pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) {
356
- self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1);
357
- }
358
- }
359
-
360
- /// A raw hash table with an unsafe API.
361
- pub struct RawTable<T, A: Allocator + Clone = Global> {
362
- table: RawTableInner<A>,
363
- // Tell dropck that we own instances of T.
364
- marker: PhantomData<T>,
365
- }
366
-
367
- /// Non-generic part of `RawTable` which allows functions to be instantiated only once regardless
368
- /// of how many different key-value types are used.
369
- struct RawTableInner<A> {
370
- // Mask to get an index from a hash value. The value is one less than the
371
- // number of buckets in the table.
372
- bucket_mask: usize,
373
-
374
- // [Padding], T1, T2, ..., Tlast, C1, C2, ...
375
- // ^ points here
376
- ctrl: NonNull<u8>,
377
-
378
- // Number of elements that can be inserted before we need to grow the table
379
- growth_left: usize,
380
-
381
- // Number of elements in the table, only really used by len()
382
- items: usize,
383
-
384
- alloc: A,
385
- }
386
-
387
- impl<T> RawTable<T, Global> {
388
- /// Creates a new empty hash table without allocating any memory.
389
- ///
390
- /// In effect this returns a table with exactly 1 bucket. However we can
391
- /// leave the data pointer dangling since that bucket is never written to
392
- /// due to our load factor forcing us to always have at least 1 free bucket.
393
- #[inline]
394
- pub const fn new() -> Self {
395
- Self {
396
- table: RawTableInner::new_in(Global),
397
- marker: PhantomData,
398
- }
399
- }
400
-
401
- /// Attempts to allocate a new hash table with at least enough capacity
402
- /// for inserting the given number of elements without reallocating.
403
- #[cfg(feature = "raw")]
404
- pub fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
405
- Self::try_with_capacity_in(capacity, Global)
406
- }
407
-
408
- /// Allocates a new hash table with at least enough capacity for inserting
409
- /// the given number of elements without reallocating.
410
- pub fn with_capacity(capacity: usize) -> Self {
411
- Self::with_capacity_in(capacity, Global)
412
- }
413
- }
414
-
415
- impl<T, A: Allocator + Clone> RawTable<T, A> {
416
- /// Creates a new empty hash table without allocating any memory, using the
417
- /// given allocator.
418
- ///
419
- /// In effect this returns a table with exactly 1 bucket. However we can
420
- /// leave the data pointer dangling since that bucket is never written to
421
- /// due to our load factor forcing us to always have at least 1 free bucket.
422
- #[inline]
423
- pub fn new_in(alloc: A) -> Self {
424
- Self {
425
- table: RawTableInner::new_in(alloc),
426
- marker: PhantomData,
427
- }
428
- }
429
-
430
- /// Allocates a new hash table with the given number of buckets.
431
- ///
432
- /// The control bytes are left uninitialized.
433
- #[cfg_attr(feature = "inline-more", inline)]
434
- unsafe fn new_uninitialized(
435
- alloc: A,
436
- buckets: usize,
437
- fallibility: Fallibility,
438
- ) -> Result<Self, TryReserveError> {
439
- debug_assert!(buckets.is_power_of_two());
440
-
441
- Ok(Self {
442
- table: RawTableInner::new_uninitialized(
443
- alloc,
444
- TableLayout::new::<T>(),
445
- buckets,
446
- fallibility,
447
- )?,
448
- marker: PhantomData,
449
- })
450
- }
451
-
452
- /// Attempts to allocate a new hash table with at least enough capacity
453
- /// for inserting the given number of elements without reallocating.
454
- fn fallible_with_capacity(
455
- alloc: A,
456
- capacity: usize,
457
- fallibility: Fallibility,
458
- ) -> Result<Self, TryReserveError> {
459
- Ok(Self {
460
- table: RawTableInner::fallible_with_capacity(
461
- alloc,
462
- TableLayout::new::<T>(),
463
- capacity,
464
- fallibility,
465
- )?,
466
- marker: PhantomData,
467
- })
468
- }
469
-
470
- /// Attempts to allocate a new hash table using the given allocator, with at least enough
471
- /// capacity for inserting the given number of elements without reallocating.
472
- #[cfg(feature = "raw")]
473
- pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> {
474
- Self::fallible_with_capacity(alloc, capacity, Fallibility::Fallible)
475
- }
476
-
477
- /// Allocates a new hash table using the given allocator, with at least enough capacity for
478
- /// inserting the given number of elements without reallocating.
479
- pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
480
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
481
- match Self::fallible_with_capacity(alloc, capacity, Fallibility::Infallible) {
482
- Ok(capacity) => capacity,
483
- Err(_) => unsafe { hint::unreachable_unchecked() },
484
- }
485
- }
486
-
487
- /// Returns a reference to the underlying allocator.
488
- #[inline]
489
- pub fn allocator(&self) -> &A {
490
- &self.table.alloc
491
- }
492
-
493
- /// Deallocates the table without dropping any entries.
494
- #[cfg_attr(feature = "inline-more", inline)]
495
- unsafe fn free_buckets(&mut self) {
496
- self.table.free_buckets(TableLayout::new::<T>());
497
- }
498
-
499
- /// Returns pointer to one past last element of data table.
500
- #[inline]
501
- pub unsafe fn data_end(&self) -> NonNull<T> {
502
- NonNull::new_unchecked(self.table.ctrl.as_ptr().cast())
503
- }
504
-
505
- /// Returns pointer to start of data table.
506
- #[inline]
507
- #[cfg(feature = "nightly")]
508
- pub unsafe fn data_start(&self) -> *mut T {
509
- self.data_end().as_ptr().wrapping_sub(self.buckets())
510
- }
511
-
512
- /// Returns the index of a bucket from a `Bucket`.
513
- #[inline]
514
- pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
515
- bucket.to_base_index(self.data_end())
516
- }
517
-
518
- /// Returns a pointer to an element in the table.
519
- #[inline]
520
- pub unsafe fn bucket(&self, index: usize) -> Bucket<T> {
521
- debug_assert_ne!(self.table.bucket_mask, 0);
522
- debug_assert!(index < self.buckets());
523
- Bucket::from_base_index(self.data_end(), index)
524
- }
525
-
526
- /// Erases an element from the table without dropping it.
527
- #[cfg_attr(feature = "inline-more", inline)]
528
- #[deprecated(since = "0.8.1", note = "use erase or remove instead")]
529
- pub unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
530
- let index = self.bucket_index(item);
531
- self.table.erase(index);
532
- }
533
-
534
- /// Erases an element from the table, dropping it in place.
535
- #[cfg_attr(feature = "inline-more", inline)]
536
- #[allow(clippy::needless_pass_by_value)]
537
- #[allow(deprecated)]
538
- pub unsafe fn erase(&mut self, item: Bucket<T>) {
539
- // Erase the element from the table first since drop might panic.
540
- self.erase_no_drop(&item);
541
- item.drop();
542
- }
543
-
544
- /// Finds and erases an element from the table, dropping it in place.
545
- /// Returns true if an element was found.
546
- #[cfg(feature = "raw")]
547
- #[cfg_attr(feature = "inline-more", inline)]
548
- pub fn erase_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> bool {
549
- // Avoid `Option::map` because it bloats LLVM IR.
550
- if let Some(bucket) = self.find(hash, eq) {
551
- unsafe {
552
- self.erase(bucket);
553
- }
554
- true
555
- } else {
556
- false
557
- }
558
- }
559
-
560
- /// Removes an element from the table, returning it.
561
- #[cfg_attr(feature = "inline-more", inline)]
562
- #[allow(clippy::needless_pass_by_value)]
563
- #[allow(deprecated)]
564
- pub unsafe fn remove(&mut self, item: Bucket<T>) -> T {
565
- self.erase_no_drop(&item);
566
- item.read()
567
- }
568
-
569
- /// Finds and removes an element from the table, returning it.
570
- #[cfg_attr(feature = "inline-more", inline)]
571
- pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<T> {
572
- // Avoid `Option::map` because it bloats LLVM IR.
573
- match self.find(hash, eq) {
574
- Some(bucket) => Some(unsafe { self.remove(bucket) }),
575
- None => None,
576
- }
577
- }
578
-
579
- /// Marks all table buckets as empty without dropping their contents.
580
- #[cfg_attr(feature = "inline-more", inline)]
581
- pub fn clear_no_drop(&mut self) {
582
- self.table.clear_no_drop();
583
- }
584
-
585
- /// Removes all elements from the table without freeing the backing memory.
586
- #[cfg_attr(feature = "inline-more", inline)]
587
- pub fn clear(&mut self) {
588
- // Ensure that the table is reset even if one of the drops panic
589
- let mut self_ = guard(self, |self_| self_.clear_no_drop());
590
- unsafe {
591
- self_.drop_elements();
592
- }
593
- }
594
-
595
- unsafe fn drop_elements(&mut self) {
596
- if mem::needs_drop::<T>() && !self.is_empty() {
597
- for item in self.iter() {
598
- item.drop();
599
- }
600
- }
601
- }
602
-
603
- /// Shrinks the table to fit `max(self.len(), min_size)` elements.
604
- #[cfg_attr(feature = "inline-more", inline)]
605
- pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) {
606
- // Calculate the minimal number of elements that we need to reserve
607
- // space for.
608
- let min_size = usize::max(self.table.items, min_size);
609
- if min_size == 0 {
610
- *self = Self::new_in(self.table.alloc.clone());
611
- return;
612
- }
613
-
614
- // Calculate the number of buckets that we need for this number of
615
- // elements. If the calculation overflows then the requested bucket
616
- // count must be larger than what we have right and nothing needs to be
617
- // done.
618
- let min_buckets = match capacity_to_buckets(min_size) {
619
- Some(buckets) => buckets,
620
- None => return,
621
- };
622
-
623
- // If we have more buckets than we need, shrink the table.
624
- if min_buckets < self.buckets() {
625
- // Fast path if the table is empty
626
- if self.table.items == 0 {
627
- *self = Self::with_capacity_in(min_size, self.table.alloc.clone());
628
- } else {
629
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
630
- if self
631
- .resize(min_size, hasher, Fallibility::Infallible)
632
- .is_err()
633
- {
634
- unsafe { hint::unreachable_unchecked() }
635
- }
636
- }
637
- }
638
- }
639
-
640
- /// Ensures that at least `additional` items can be inserted into the table
641
- /// without reallocation.
642
- #[cfg_attr(feature = "inline-more", inline)]
643
- pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
644
- if additional > self.table.growth_left {
645
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
646
- if self
647
- .reserve_rehash(additional, hasher, Fallibility::Infallible)
648
- .is_err()
649
- {
650
- unsafe { hint::unreachable_unchecked() }
651
- }
652
- }
653
- }
654
-
655
- /// Tries to ensure that at least `additional` items can be inserted into
656
- /// the table without reallocation.
657
- #[cfg_attr(feature = "inline-more", inline)]
658
- pub fn try_reserve(
659
- &mut self,
660
- additional: usize,
661
- hasher: impl Fn(&T) -> u64,
662
- ) -> Result<(), TryReserveError> {
663
- if additional > self.table.growth_left {
664
- self.reserve_rehash(additional, hasher, Fallibility::Fallible)
665
- } else {
666
- Ok(())
667
- }
668
- }
669
-
670
- /// Out-of-line slow path for `reserve` and `try_reserve`.
671
- #[cold]
672
- #[inline(never)]
673
- fn reserve_rehash(
674
- &mut self,
675
- additional: usize,
676
- hasher: impl Fn(&T) -> u64,
677
- fallibility: Fallibility,
678
- ) -> Result<(), TryReserveError> {
679
- unsafe {
680
- self.table.reserve_rehash_inner(
681
- additional,
682
- &|table, index| hasher(table.bucket::<T>(index).as_ref()),
683
- fallibility,
684
- TableLayout::new::<T>(),
685
- if mem::needs_drop::<T>() {
686
- Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T)))
687
- } else {
688
- None
689
- },
690
- )
691
- }
692
- }
693
-
694
- /// Allocates a new table of a different size and moves the contents of the
695
- /// current table into it.
696
- fn resize(
697
- &mut self,
698
- capacity: usize,
699
- hasher: impl Fn(&T) -> u64,
700
- fallibility: Fallibility,
701
- ) -> Result<(), TryReserveError> {
702
- unsafe {
703
- self.table.resize_inner(
704
- capacity,
705
- &|table, index| hasher(table.bucket::<T>(index).as_ref()),
706
- fallibility,
707
- TableLayout::new::<T>(),
708
- )
709
- }
710
- }
711
-
712
- /// Inserts a new element into the table, and returns its raw bucket.
713
- ///
714
- /// This does not check if the given element already exists in the table.
715
- #[cfg_attr(feature = "inline-more", inline)]
716
- pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
717
- unsafe {
718
- let mut index = self.table.find_insert_slot(hash);
719
-
720
- // We can avoid growing the table once we have reached our load
721
- // factor if we are replacing a tombstone. This works since the
722
- // number of EMPTY slots does not change in this case.
723
- let old_ctrl = *self.table.ctrl(index);
724
- if unlikely(self.table.growth_left == 0 && special_is_empty(old_ctrl)) {
725
- self.reserve(1, hasher);
726
- index = self.table.find_insert_slot(hash);
727
- }
728
-
729
- self.table.record_item_insert_at(index, old_ctrl, hash);
730
-
731
- let bucket = self.bucket(index);
732
- bucket.write(value);
733
- bucket
734
- }
735
- }
736
-
737
- /// Attempts to insert a new element without growing the table and return its raw bucket.
738
- ///
739
- /// Returns an `Err` containing the given element if inserting it would require growing the
740
- /// table.
741
- ///
742
- /// This does not check if the given element already exists in the table.
743
- #[cfg(feature = "raw")]
744
- #[cfg_attr(feature = "inline-more", inline)]
745
- pub fn try_insert_no_grow(&mut self, hash: u64, value: T) -> Result<Bucket<T>, T> {
746
- unsafe {
747
- match self.table.prepare_insert_no_grow(hash) {
748
- Ok(index) => {
749
- let bucket = self.bucket(index);
750
- bucket.write(value);
751
- Ok(bucket)
752
- }
753
- Err(()) => Err(value),
754
- }
755
- }
756
- }
757
-
758
- /// Inserts a new element into the table, and returns a mutable reference to it.
759
- ///
760
- /// This does not check if the given element already exists in the table.
761
- #[cfg_attr(feature = "inline-more", inline)]
762
- pub fn insert_entry(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> &mut T {
763
- unsafe { self.insert(hash, value, hasher).as_mut() }
764
- }
765
-
766
- /// Inserts a new element into the table, without growing the table.
767
- ///
768
- /// There must be enough space in the table to insert the new element.
769
- ///
770
- /// This does not check if the given element already exists in the table.
771
- #[cfg_attr(feature = "inline-more", inline)]
772
- #[cfg(any(feature = "raw", feature = "rustc-internal-api"))]
773
- pub unsafe fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> {
774
- let (index, old_ctrl) = self.table.prepare_insert_slot(hash);
775
- let bucket = self.table.bucket(index);
776
-
777
- // If we are replacing a DELETED entry then we don't need to update
778
- // the load counter.
779
- self.table.growth_left -= special_is_empty(old_ctrl) as usize;
780
-
781
- bucket.write(value);
782
- self.table.items += 1;
783
- bucket
784
- }
785
-
786
- /// Temporary removes a bucket, applying the given function to the removed
787
- /// element and optionally put back the returned value in the same bucket.
788
- ///
789
- /// Returns `true` if the bucket still contains an element
790
- ///
791
- /// This does not check if the given bucket is actually occupied.
792
- #[cfg_attr(feature = "inline-more", inline)]
793
- pub unsafe fn replace_bucket_with<F>(&mut self, bucket: Bucket<T>, f: F) -> bool
794
- where
795
- F: FnOnce(T) -> Option<T>,
796
- {
797
- let index = self.bucket_index(&bucket);
798
- let old_ctrl = *self.table.ctrl(index);
799
- debug_assert!(is_full(old_ctrl));
800
- let old_growth_left = self.table.growth_left;
801
- let item = self.remove(bucket);
802
- if let Some(new_item) = f(item) {
803
- self.table.growth_left = old_growth_left;
804
- self.table.set_ctrl(index, old_ctrl);
805
- self.table.items += 1;
806
- self.bucket(index).write(new_item);
807
- true
808
- } else {
809
- false
810
- }
811
- }
812
-
813
- /// Searches for an element in the table.
814
- #[inline]
815
- pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
816
- let result = self.table.find_inner(hash, &mut |index| unsafe {
817
- eq(self.bucket(index).as_ref())
818
- });
819
-
820
- // Avoid `Option::map` because it bloats LLVM IR.
821
- match result {
822
- Some(index) => Some(unsafe { self.bucket(index) }),
823
- None => None,
824
- }
825
- }
826
-
827
- /// Gets a reference to an element in the table.
828
- #[inline]
829
- pub fn get(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> {
830
- // Avoid `Option::map` because it bloats LLVM IR.
831
- match self.find(hash, eq) {
832
- Some(bucket) => Some(unsafe { bucket.as_ref() }),
833
- None => None,
834
- }
835
- }
836
-
837
- /// Gets a mutable reference to an element in the table.
838
- #[inline]
839
- pub fn get_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> {
840
- // Avoid `Option::map` because it bloats LLVM IR.
841
- match self.find(hash, eq) {
842
- Some(bucket) => Some(unsafe { bucket.as_mut() }),
843
- None => None,
844
- }
845
- }
846
-
847
- /// Attempts to get mutable references to `N` entries in the table at once.
848
- ///
849
- /// Returns an array of length `N` with the results of each query.
850
- ///
851
- /// At most one mutable reference will be returned to any entry. `None` will be returned if any
852
- /// of the hashes are duplicates. `None` will be returned if the hash is not found.
853
- ///
854
- /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
855
- /// the `i`th key to be looked up.
856
- pub fn get_many_mut<const N: usize>(
857
- &mut self,
858
- hashes: [u64; N],
859
- eq: impl FnMut(usize, &T) -> bool,
860
- ) -> Option<[&'_ mut T; N]> {
861
- unsafe {
862
- let ptrs = self.get_many_mut_pointers(hashes, eq)?;
863
-
864
- for (i, &cur) in ptrs.iter().enumerate() {
865
- if ptrs[..i].iter().any(|&prev| ptr::eq::<T>(prev, cur)) {
866
- return None;
867
- }
868
- }
869
- // All bucket are distinct from all previous buckets so we're clear to return the result
870
- // of the lookup.
871
-
872
- // TODO use `MaybeUninit::array_assume_init` here instead once that's stable.
873
- Some(mem::transmute_copy(&ptrs))
874
- }
875
- }
876
-
877
- pub unsafe fn get_many_unchecked_mut<const N: usize>(
878
- &mut self,
879
- hashes: [u64; N],
880
- eq: impl FnMut(usize, &T) -> bool,
881
- ) -> Option<[&'_ mut T; N]> {
882
- let ptrs = self.get_many_mut_pointers(hashes, eq)?;
883
- Some(mem::transmute_copy(&ptrs))
884
- }
885
-
886
- unsafe fn get_many_mut_pointers<const N: usize>(
887
- &mut self,
888
- hashes: [u64; N],
889
- mut eq: impl FnMut(usize, &T) -> bool,
890
- ) -> Option<[*mut T; N]> {
891
- // TODO use `MaybeUninit::uninit_array` here instead once that's stable.
892
- let mut outs: MaybeUninit<[*mut T; N]> = MaybeUninit::uninit();
893
- let outs_ptr = outs.as_mut_ptr();
894
-
895
- for (i, &hash) in hashes.iter().enumerate() {
896
- let cur = self.find(hash, |k| eq(i, k))?;
897
- *(*outs_ptr).get_unchecked_mut(i) = cur.as_mut();
898
- }
899
-
900
- // TODO use `MaybeUninit::array_assume_init` here instead once that's stable.
901
- Some(outs.assume_init())
902
- }
903
-
904
- /// Returns the number of elements the map can hold without reallocating.
905
- ///
906
- /// This number is a lower bound; the table might be able to hold
907
- /// more, but is guaranteed to be able to hold at least this many.
908
- #[inline]
909
- pub fn capacity(&self) -> usize {
910
- self.table.items + self.table.growth_left
911
- }
912
-
913
- /// Returns the number of elements in the table.
914
- #[inline]
915
- pub fn len(&self) -> usize {
916
- self.table.items
917
- }
918
-
919
- /// Returns `true` if the table contains no elements.
920
- #[inline]
921
- pub fn is_empty(&self) -> bool {
922
- self.len() == 0
923
- }
924
-
925
- /// Returns the number of buckets in the table.
926
- #[inline]
927
- pub fn buckets(&self) -> usize {
928
- self.table.bucket_mask + 1
929
- }
930
-
931
- /// Returns an iterator over every element in the table. It is up to
932
- /// the caller to ensure that the `RawTable` outlives the `RawIter`.
933
- /// Because we cannot make the `next` method unsafe on the `RawIter`
934
- /// struct, we have to make the `iter` method unsafe.
935
- #[inline]
936
- pub unsafe fn iter(&self) -> RawIter<T> {
937
- let data = Bucket::from_base_index(self.data_end(), 0);
938
- RawIter {
939
- iter: RawIterRange::new(self.table.ctrl.as_ptr(), data, self.table.buckets()),
940
- items: self.table.items,
941
- }
942
- }
943
-
944
- /// Returns an iterator over occupied buckets that could match a given hash.
945
- ///
946
- /// `RawTable` only stores 7 bits of the hash value, so this iterator may
947
- /// return items that have a hash value different than the one provided. You
948
- /// should always validate the returned values before using them.
949
- ///
950
- /// It is up to the caller to ensure that the `RawTable` outlives the
951
- /// `RawIterHash`. Because we cannot make the `next` method unsafe on the
952
- /// `RawIterHash` struct, we have to make the `iter_hash` method unsafe.
953
- #[cfg_attr(feature = "inline-more", inline)]
954
- #[cfg(feature = "raw")]
955
- pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<'_, T, A> {
956
- RawIterHash::new(self, hash)
957
- }
958
-
959
- /// Returns an iterator which removes all elements from the table without
960
- /// freeing the memory.
961
- #[cfg_attr(feature = "inline-more", inline)]
962
- pub fn drain(&mut self) -> RawDrain<'_, T, A> {
963
- unsafe {
964
- let iter = self.iter();
965
- self.drain_iter_from(iter)
966
- }
967
- }
968
-
969
- /// Returns an iterator which removes all elements from the table without
970
- /// freeing the memory.
971
- ///
972
- /// Iteration starts at the provided iterator's current location.
973
- ///
974
- /// It is up to the caller to ensure that the iterator is valid for this
975
- /// `RawTable` and covers all items that remain in the table.
976
- #[cfg_attr(feature = "inline-more", inline)]
977
- pub unsafe fn drain_iter_from(&mut self, iter: RawIter<T>) -> RawDrain<'_, T, A> {
978
- debug_assert_eq!(iter.len(), self.len());
979
- RawDrain {
980
- iter,
981
- table: ManuallyDrop::new(mem::replace(self, Self::new_in(self.table.alloc.clone()))),
982
- orig_table: NonNull::from(self),
983
- marker: PhantomData,
984
- }
985
- }
986
-
987
- /// Returns an iterator which consumes all elements from the table.
988
- ///
989
- /// Iteration starts at the provided iterator's current location.
990
- ///
991
- /// It is up to the caller to ensure that the iterator is valid for this
992
- /// `RawTable` and covers all items that remain in the table.
993
- pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T, A> {
994
- debug_assert_eq!(iter.len(), self.len());
995
-
996
- let alloc = self.table.alloc.clone();
997
- let allocation = self.into_allocation();
998
- RawIntoIter {
999
- iter,
1000
- allocation,
1001
- marker: PhantomData,
1002
- alloc,
1003
- }
1004
- }
1005
-
1006
- /// Converts the table into a raw allocation. The contents of the table
1007
- /// should be dropped using a `RawIter` before freeing the allocation.
1008
- #[cfg_attr(feature = "inline-more", inline)]
1009
- pub(crate) fn into_allocation(self) -> Option<(NonNull<u8>, Layout)> {
1010
- let alloc = if self.table.is_empty_singleton() {
1011
- None
1012
- } else {
1013
- // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
1014
- let (layout, ctrl_offset) = match calculate_layout::<T>(self.table.buckets()) {
1015
- Some(lco) => lco,
1016
- None => unsafe { hint::unreachable_unchecked() },
1017
- };
1018
- Some((
1019
- unsafe { NonNull::new_unchecked(self.table.ctrl.as_ptr().sub(ctrl_offset)) },
1020
- layout,
1021
- ))
1022
- };
1023
- mem::forget(self);
1024
- alloc
1025
- }
1026
- }
1027
-
1028
- unsafe impl<T, A: Allocator + Clone> Send for RawTable<T, A>
1029
- where
1030
- T: Send,
1031
- A: Send,
1032
- {
1033
- }
1034
- unsafe impl<T, A: Allocator + Clone> Sync for RawTable<T, A>
1035
- where
1036
- T: Sync,
1037
- A: Sync,
1038
- {
1039
- }
1040
-
1041
- impl<A> RawTableInner<A> {
1042
- #[inline]
1043
- const fn new_in(alloc: A) -> Self {
1044
- Self {
1045
- // Be careful to cast the entire slice to a raw pointer.
1046
- ctrl: unsafe { NonNull::new_unchecked(Group::static_empty() as *const _ as *mut u8) },
1047
- bucket_mask: 0,
1048
- items: 0,
1049
- growth_left: 0,
1050
- alloc,
1051
- }
1052
- }
1053
- }
1054
-
1055
- impl<A: Allocator + Clone> RawTableInner<A> {
1056
- #[cfg_attr(feature = "inline-more", inline)]
1057
- unsafe fn new_uninitialized(
1058
- alloc: A,
1059
- table_layout: TableLayout,
1060
- buckets: usize,
1061
- fallibility: Fallibility,
1062
- ) -> Result<Self, TryReserveError> {
1063
- debug_assert!(buckets.is_power_of_two());
1064
-
1065
- // Avoid `Option::ok_or_else` because it bloats LLVM IR.
1066
- let (layout, ctrl_offset) = match table_layout.calculate_layout_for(buckets) {
1067
- Some(lco) => lco,
1068
- None => return Err(fallibility.capacity_overflow()),
1069
- };
1070
-
1071
- // We need an additional check to ensure that the allocation doesn't
1072
- // exceed `isize::MAX`. We can skip this check on 64-bit systems since
1073
- // such allocations will never succeed anyways.
1074
- //
1075
- // This mirrors what Vec does in the standard library.
1076
- if mem::size_of::<usize>() < 8 && layout.size() > isize::MAX as usize {
1077
- return Err(fallibility.capacity_overflow());
1078
- }
1079
-
1080
- let ptr: NonNull<u8> = match do_alloc(&alloc, layout) {
1081
- Ok(block) => block.cast(),
1082
- Err(_) => return Err(fallibility.alloc_err(layout)),
1083
- };
1084
-
1085
- let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
1086
- Ok(Self {
1087
- ctrl,
1088
- bucket_mask: buckets - 1,
1089
- items: 0,
1090
- growth_left: bucket_mask_to_capacity(buckets - 1),
1091
- alloc,
1092
- })
1093
- }
1094
-
1095
- #[inline]
1096
- fn fallible_with_capacity(
1097
- alloc: A,
1098
- table_layout: TableLayout,
1099
- capacity: usize,
1100
- fallibility: Fallibility,
1101
- ) -> Result<Self, TryReserveError> {
1102
- if capacity == 0 {
1103
- Ok(Self::new_in(alloc))
1104
- } else {
1105
- unsafe {
1106
- let buckets =
1107
- capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?;
1108
-
1109
- let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?;
1110
- result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
1111
-
1112
- Ok(result)
1113
- }
1114
- }
1115
- }
1116
-
1117
- /// Searches for an empty or deleted bucket which is suitable for inserting
1118
- /// a new element and sets the hash for that slot.
1119
- ///
1120
- /// There must be at least 1 empty bucket in the table.
1121
- #[inline]
1122
- unsafe fn prepare_insert_slot(&self, hash: u64) -> (usize, u8) {
1123
- let index = self.find_insert_slot(hash);
1124
- let old_ctrl = *self.ctrl(index);
1125
- self.set_ctrl_h2(index, hash);
1126
- (index, old_ctrl)
1127
- }
1128
-
1129
- /// Searches for an empty or deleted bucket which is suitable for inserting
1130
- /// a new element.
1131
- ///
1132
- /// There must be at least 1 empty bucket in the table.
1133
- #[inline]
1134
- fn find_insert_slot(&self, hash: u64) -> usize {
1135
- let mut probe_seq = self.probe_seq(hash);
1136
- loop {
1137
- unsafe {
1138
- let group = Group::load(self.ctrl(probe_seq.pos));
1139
- if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() {
1140
- let result = (probe_seq.pos + bit) & self.bucket_mask;
1141
-
1142
- // In tables smaller than the group width, trailing control
1143
- // bytes outside the range of the table are filled with
1144
- // EMPTY entries. These will unfortunately trigger a
1145
- // match, but once masked may point to a full bucket that
1146
- // is already occupied. We detect this situation here and
1147
- // perform a second scan starting at the beginning of the
1148
- // table. This second scan is guaranteed to find an empty
1149
- // slot (due to the load factor) before hitting the trailing
1150
- // control bytes (containing EMPTY).
1151
- if unlikely(is_full(*self.ctrl(result))) {
1152
- debug_assert!(self.bucket_mask < Group::WIDTH);
1153
- debug_assert_ne!(probe_seq.pos, 0);
1154
- return Group::load_aligned(self.ctrl(0))
1155
- .match_empty_or_deleted()
1156
- .lowest_set_bit_nonzero();
1157
- }
1158
-
1159
- return result;
1160
- }
1161
- }
1162
- probe_seq.move_next(self.bucket_mask);
1163
- }
1164
- }
1165
-
1166
- /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of
1167
- /// code generated, but it is eliminated by LLVM optimizations.
1168
- #[inline]
1169
- fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> {
1170
- let h2_hash = h2(hash);
1171
- let mut probe_seq = self.probe_seq(hash);
1172
-
1173
- loop {
1174
- let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
1175
-
1176
- for bit in group.match_byte(h2_hash) {
1177
- let index = (probe_seq.pos + bit) & self.bucket_mask;
1178
-
1179
- if likely(eq(index)) {
1180
- return Some(index);
1181
- }
1182
- }
1183
-
1184
- if likely(group.match_empty().any_bit_set()) {
1185
- return None;
1186
- }
1187
-
1188
- probe_seq.move_next(self.bucket_mask);
1189
- }
1190
- }
1191
-
1192
- #[allow(clippy::mut_mut)]
1193
- #[inline]
1194
- unsafe fn prepare_rehash_in_place(&mut self) {
1195
- // Bulk convert all full control bytes to DELETED, and all DELETED
1196
- // control bytes to EMPTY. This effectively frees up all buckets
1197
- // containing a DELETED entry.
1198
- for i in (0..self.buckets()).step_by(Group::WIDTH) {
1199
- let group = Group::load_aligned(self.ctrl(i));
1200
- let group = group.convert_special_to_empty_and_full_to_deleted();
1201
- group.store_aligned(self.ctrl(i));
1202
- }
1203
-
1204
- // Fix up the trailing control bytes. See the comments in set_ctrl
1205
- // for the handling of tables smaller than the group width.
1206
- if self.buckets() < Group::WIDTH {
1207
- self.ctrl(0)
1208
- .copy_to(self.ctrl(Group::WIDTH), self.buckets());
1209
- } else {
1210
- self.ctrl(0)
1211
- .copy_to(self.ctrl(self.buckets()), Group::WIDTH);
1212
- }
1213
- }
1214
-
1215
- #[inline]
1216
- unsafe fn bucket<T>(&self, index: usize) -> Bucket<T> {
1217
- debug_assert_ne!(self.bucket_mask, 0);
1218
- debug_assert!(index < self.buckets());
1219
- Bucket::from_base_index(self.data_end(), index)
1220
- }
1221
-
1222
- #[inline]
1223
- unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 {
1224
- debug_assert_ne!(self.bucket_mask, 0);
1225
- debug_assert!(index < self.buckets());
1226
- let base: *mut u8 = self.data_end().as_ptr();
1227
- base.sub((index + 1) * size_of)
1228
- }
1229
-
1230
- #[inline]
1231
- unsafe fn data_end<T>(&self) -> NonNull<T> {
1232
- NonNull::new_unchecked(self.ctrl.as_ptr().cast())
1233
- }
1234
-
1235
- /// Returns an iterator-like object for a probe sequence on the table.
1236
- ///
1237
- /// This iterator never terminates, but is guaranteed to visit each bucket
1238
- /// group exactly once. The loop using `probe_seq` must terminate upon
1239
- /// reaching a group containing an empty bucket.
1240
- #[inline]
1241
- fn probe_seq(&self, hash: u64) -> ProbeSeq {
1242
- ProbeSeq {
1243
- pos: h1(hash) & self.bucket_mask,
1244
- stride: 0,
1245
- }
1246
- }
1247
-
1248
- /// Returns the index of a bucket for which a value must be inserted if there is enough rooom
1249
- /// in the table, otherwise returns error
1250
- #[cfg(feature = "raw")]
1251
- #[inline]
1252
- unsafe fn prepare_insert_no_grow(&mut self, hash: u64) -> Result<usize, ()> {
1253
- let index = self.find_insert_slot(hash);
1254
- let old_ctrl = *self.ctrl(index);
1255
- if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) {
1256
- Err(())
1257
- } else {
1258
- self.record_item_insert_at(index, old_ctrl, hash);
1259
- Ok(index)
1260
- }
1261
- }
1262
-
1263
- #[inline]
1264
- unsafe fn record_item_insert_at(&mut self, index: usize, old_ctrl: u8, hash: u64) {
1265
- self.growth_left -= usize::from(special_is_empty(old_ctrl));
1266
- self.set_ctrl_h2(index, hash);
1267
- self.items += 1;
1268
- }
1269
-
1270
- #[inline]
1271
- fn is_in_same_group(&self, i: usize, new_i: usize, hash: u64) -> bool {
1272
- let probe_seq_pos = self.probe_seq(hash).pos;
1273
- let probe_index =
1274
- |pos: usize| (pos.wrapping_sub(probe_seq_pos) & self.bucket_mask) / Group::WIDTH;
1275
- probe_index(i) == probe_index(new_i)
1276
- }
1277
-
1278
- /// Sets a control byte to the hash, and possibly also the replicated control byte at
1279
- /// the end of the array.
1280
- #[inline]
1281
- unsafe fn set_ctrl_h2(&self, index: usize, hash: u64) {
1282
- self.set_ctrl(index, h2(hash));
1283
- }
1284
-
1285
- #[inline]
1286
- unsafe fn replace_ctrl_h2(&self, index: usize, hash: u64) -> u8 {
1287
- let prev_ctrl = *self.ctrl(index);
1288
- self.set_ctrl_h2(index, hash);
1289
- prev_ctrl
1290
- }
1291
-
1292
- /// Sets a control byte, and possibly also the replicated control byte at
1293
- /// the end of the array.
1294
- #[inline]
1295
- unsafe fn set_ctrl(&self, index: usize, ctrl: u8) {
1296
- // Replicate the first Group::WIDTH control bytes at the end of
1297
- // the array without using a branch:
1298
- // - If index >= Group::WIDTH then index == index2.
1299
- // - Otherwise index2 == self.bucket_mask + 1 + index.
1300
- //
1301
- // The very last replicated control byte is never actually read because
1302
- // we mask the initial index for unaligned loads, but we write it
1303
- // anyways because it makes the set_ctrl implementation simpler.
1304
- //
1305
- // If there are fewer buckets than Group::WIDTH then this code will
1306
- // replicate the buckets at the end of the trailing group. For example
1307
- // with 2 buckets and a group size of 4, the control bytes will look
1308
- // like this:
1309
- //
1310
- // Real | Replicated
1311
- // ---------------------------------------------
1312
- // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] |
1313
- // ---------------------------------------------
1314
- let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH;
1315
-
1316
- *self.ctrl(index) = ctrl;
1317
- *self.ctrl(index2) = ctrl;
1318
- }
1319
-
1320
- /// Returns a pointer to a control byte.
1321
- #[inline]
1322
- unsafe fn ctrl(&self, index: usize) -> *mut u8 {
1323
- debug_assert!(index < self.num_ctrl_bytes());
1324
- self.ctrl.as_ptr().add(index)
1325
- }
1326
-
1327
- #[inline]
1328
- fn buckets(&self) -> usize {
1329
- self.bucket_mask + 1
1330
- }
1331
-
1332
- #[inline]
1333
- fn num_ctrl_bytes(&self) -> usize {
1334
- self.bucket_mask + 1 + Group::WIDTH
1335
- }
1336
-
1337
- #[inline]
1338
- fn is_empty_singleton(&self) -> bool {
1339
- self.bucket_mask == 0
1340
- }
1341
-
1342
- #[allow(clippy::mut_mut)]
1343
- #[inline]
1344
- unsafe fn prepare_resize(
1345
- &self,
1346
- table_layout: TableLayout,
1347
- capacity: usize,
1348
- fallibility: Fallibility,
1349
- ) -> Result<crate::scopeguard::ScopeGuard<Self, impl FnMut(&mut Self)>, TryReserveError> {
1350
- debug_assert!(self.items <= capacity);
1351
-
1352
- // Allocate and initialize the new table.
1353
- let mut new_table = RawTableInner::fallible_with_capacity(
1354
- self.alloc.clone(),
1355
- table_layout,
1356
- capacity,
1357
- fallibility,
1358
- )?;
1359
- new_table.growth_left -= self.items;
1360
- new_table.items = self.items;
1361
-
1362
- // The hash function may panic, in which case we simply free the new
1363
- // table without dropping any elements that may have been copied into
1364
- // it.
1365
- //
1366
- // This guard is also used to free the old table on success, see
1367
- // the comment at the bottom of this function.
1368
- Ok(guard(new_table, move |self_| {
1369
- if !self_.is_empty_singleton() {
1370
- self_.free_buckets(table_layout);
1371
- }
1372
- }))
1373
- }
1374
-
1375
- /// Reserves or rehashes to make room for `additional` more elements.
1376
- ///
1377
- /// This uses dynamic dispatch to reduce the amount of
1378
- /// code generated, but it is eliminated by LLVM optimizations when inlined.
1379
- #[allow(clippy::inline_always)]
1380
- #[inline(always)]
1381
- unsafe fn reserve_rehash_inner(
1382
- &mut self,
1383
- additional: usize,
1384
- hasher: &dyn Fn(&mut Self, usize) -> u64,
1385
- fallibility: Fallibility,
1386
- layout: TableLayout,
1387
- drop: Option<fn(*mut u8)>,
1388
- ) -> Result<(), TryReserveError> {
1389
- // Avoid `Option::ok_or_else` because it bloats LLVM IR.
1390
- let new_items = match self.items.checked_add(additional) {
1391
- Some(new_items) => new_items,
1392
- None => return Err(fallibility.capacity_overflow()),
1393
- };
1394
- let full_capacity = bucket_mask_to_capacity(self.bucket_mask);
1395
- if new_items <= full_capacity / 2 {
1396
- // Rehash in-place without re-allocating if we have plenty of spare
1397
- // capacity that is locked up due to DELETED entries.
1398
- self.rehash_in_place(hasher, layout.size, drop);
1399
- Ok(())
1400
- } else {
1401
- // Otherwise, conservatively resize to at least the next size up
1402
- // to avoid churning deletes into frequent rehashes.
1403
- self.resize_inner(
1404
- usize::max(new_items, full_capacity + 1),
1405
- hasher,
1406
- fallibility,
1407
- layout,
1408
- )
1409
- }
1410
- }
1411
-
1412
- /// Allocates a new table of a different size and moves the contents of the
1413
- /// current table into it.
1414
- ///
1415
- /// This uses dynamic dispatch to reduce the amount of
1416
- /// code generated, but it is eliminated by LLVM optimizations when inlined.
1417
- #[allow(clippy::inline_always)]
1418
- #[inline(always)]
1419
- unsafe fn resize_inner(
1420
- &mut self,
1421
- capacity: usize,
1422
- hasher: &dyn Fn(&mut Self, usize) -> u64,
1423
- fallibility: Fallibility,
1424
- layout: TableLayout,
1425
- ) -> Result<(), TryReserveError> {
1426
- let mut new_table = self.prepare_resize(layout, capacity, fallibility)?;
1427
-
1428
- // Copy all elements to the new table.
1429
- for i in 0..self.buckets() {
1430
- if !is_full(*self.ctrl(i)) {
1431
- continue;
1432
- }
1433
-
1434
- // This may panic.
1435
- let hash = hasher(self, i);
1436
-
1437
- // We can use a simpler version of insert() here since:
1438
- // - there are no DELETED entries.
1439
- // - we know there is enough space in the table.
1440
- // - all elements are unique.
1441
- let (index, _) = new_table.prepare_insert_slot(hash);
1442
-
1443
- ptr::copy_nonoverlapping(
1444
- self.bucket_ptr(i, layout.size),
1445
- new_table.bucket_ptr(index, layout.size),
1446
- layout.size,
1447
- );
1448
- }
1449
-
1450
- // We successfully copied all elements without panicking. Now replace
1451
- // self with the new table. The old table will have its memory freed but
1452
- // the items will not be dropped (since they have been moved into the
1453
- // new table).
1454
- mem::swap(self, &mut new_table);
1455
-
1456
- Ok(())
1457
- }
1458
-
1459
- /// Rehashes the contents of the table in place (i.e. without changing the
1460
- /// allocation).
1461
- ///
1462
- /// If `hasher` panics then some the table's contents may be lost.
1463
- ///
1464
- /// This uses dynamic dispatch to reduce the amount of
1465
- /// code generated, but it is eliminated by LLVM optimizations when inlined.
1466
- #[allow(clippy::inline_always)]
1467
- #[cfg_attr(feature = "inline-more", inline(always))]
1468
- #[cfg_attr(not(feature = "inline-more"), inline)]
1469
- unsafe fn rehash_in_place(
1470
- &mut self,
1471
- hasher: &dyn Fn(&mut Self, usize) -> u64,
1472
- size_of: usize,
1473
- drop: Option<fn(*mut u8)>,
1474
- ) {
1475
- // If the hash function panics then properly clean up any elements
1476
- // that we haven't rehashed yet. We unfortunately can't preserve the
1477
- // element since we lost their hash and have no way of recovering it
1478
- // without risking another panic.
1479
- self.prepare_rehash_in_place();
1480
-
1481
- let mut guard = guard(self, move |self_| {
1482
- if let Some(drop) = drop {
1483
- for i in 0..self_.buckets() {
1484
- if *self_.ctrl(i) == DELETED {
1485
- self_.set_ctrl(i, EMPTY);
1486
- drop(self_.bucket_ptr(i, size_of));
1487
- self_.items -= 1;
1488
- }
1489
- }
1490
- }
1491
- self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items;
1492
- });
1493
-
1494
- // At this point, DELETED elements are elements that we haven't
1495
- // rehashed yet. Find them and re-insert them at their ideal
1496
- // position.
1497
- 'outer: for i in 0..guard.buckets() {
1498
- if *guard.ctrl(i) != DELETED {
1499
- continue;
1500
- }
1501
-
1502
- let i_p = guard.bucket_ptr(i, size_of);
1503
-
1504
- 'inner: loop {
1505
- // Hash the current item
1506
- let hash = hasher(*guard, i);
1507
-
1508
- // Search for a suitable place to put it
1509
- let new_i = guard.find_insert_slot(hash);
1510
- let new_i_p = guard.bucket_ptr(new_i, size_of);
1511
-
1512
- // Probing works by scanning through all of the control
1513
- // bytes in groups, which may not be aligned to the group
1514
- // size. If both the new and old position fall within the
1515
- // same unaligned group, then there is no benefit in moving
1516
- // it and we can just continue to the next item.
1517
- if likely(guard.is_in_same_group(i, new_i, hash)) {
1518
- guard.set_ctrl_h2(i, hash);
1519
- continue 'outer;
1520
- }
1521
-
1522
- // We are moving the current item to a new position. Write
1523
- // our H2 to the control byte of the new position.
1524
- let prev_ctrl = guard.replace_ctrl_h2(new_i, hash);
1525
- if prev_ctrl == EMPTY {
1526
- guard.set_ctrl(i, EMPTY);
1527
- // If the target slot is empty, simply move the current
1528
- // element into the new slot and clear the old control
1529
- // byte.
1530
- ptr::copy_nonoverlapping(i_p, new_i_p, size_of);
1531
- continue 'outer;
1532
- } else {
1533
- // If the target slot is occupied, swap the two elements
1534
- // and then continue processing the element that we just
1535
- // swapped into the old slot.
1536
- debug_assert_eq!(prev_ctrl, DELETED);
1537
- ptr::swap_nonoverlapping(i_p, new_i_p, size_of);
1538
- continue 'inner;
1539
- }
1540
- }
1541
- }
1542
-
1543
- guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items;
1544
-
1545
- mem::forget(guard);
1546
- }
1547
-
1548
- #[inline]
1549
- unsafe fn free_buckets(&mut self, table_layout: TableLayout) {
1550
- // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
1551
- let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
1552
- Some(lco) => lco,
1553
- None => hint::unreachable_unchecked(),
1554
- };
1555
- self.alloc.deallocate(
1556
- NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)),
1557
- layout,
1558
- );
1559
- }
1560
-
1561
- /// Marks all table buckets as empty without dropping their contents.
1562
- #[inline]
1563
- fn clear_no_drop(&mut self) {
1564
- if !self.is_empty_singleton() {
1565
- unsafe {
1566
- self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes());
1567
- }
1568
- }
1569
- self.items = 0;
1570
- self.growth_left = bucket_mask_to_capacity(self.bucket_mask);
1571
- }
1572
-
1573
- #[inline]
1574
- unsafe fn erase(&mut self, index: usize) {
1575
- debug_assert!(is_full(*self.ctrl(index)));
1576
- let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
1577
- let empty_before = Group::load(self.ctrl(index_before)).match_empty();
1578
- let empty_after = Group::load(self.ctrl(index)).match_empty();
1579
-
1580
- // If we are inside a continuous block of Group::WIDTH full or deleted
1581
- // cells then a probe window may have seen a full block when trying to
1582
- // insert. We therefore need to keep that block non-empty so that
1583
- // lookups will continue searching to the next probe window.
1584
- //
1585
- // Note that in this context `leading_zeros` refers to the bytes at the
1586
- // end of a group, while `trailing_zeros` refers to the bytes at the
1587
- // beginning of a group.
1588
- let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH {
1589
- DELETED
1590
- } else {
1591
- self.growth_left += 1;
1592
- EMPTY
1593
- };
1594
- self.set_ctrl(index, ctrl);
1595
- self.items -= 1;
1596
- }
1597
- }
1598
-
1599
- impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> {
1600
- fn clone(&self) -> Self {
1601
- if self.table.is_empty_singleton() {
1602
- Self::new_in(self.table.alloc.clone())
1603
- } else {
1604
- unsafe {
1605
- // Avoid `Result::ok_or_else` because it bloats LLVM IR.
1606
- let new_table = match Self::new_uninitialized(
1607
- self.table.alloc.clone(),
1608
- self.table.buckets(),
1609
- Fallibility::Infallible,
1610
- ) {
1611
- Ok(table) => table,
1612
- Err(_) => hint::unreachable_unchecked(),
1613
- };
1614
-
1615
- // If cloning fails then we need to free the allocation for the
1616
- // new table. However we don't run its drop since its control
1617
- // bytes are not initialized yet.
1618
- let mut guard = guard(ManuallyDrop::new(new_table), |new_table| {
1619
- new_table.free_buckets();
1620
- });
1621
-
1622
- guard.clone_from_spec(self);
1623
-
1624
- // Disarm the scope guard and return the newly created table.
1625
- ManuallyDrop::into_inner(ScopeGuard::into_inner(guard))
1626
- }
1627
- }
1628
- }
1629
-
1630
- fn clone_from(&mut self, source: &Self) {
1631
- if source.table.is_empty_singleton() {
1632
- *self = Self::new_in(self.table.alloc.clone());
1633
- } else {
1634
- unsafe {
1635
- // Make sure that if any panics occurs, we clear the table and
1636
- // leave it in an empty state.
1637
- let mut self_ = guard(self, |self_| {
1638
- self_.clear_no_drop();
1639
- });
1640
-
1641
- // First, drop all our elements without clearing the control
1642
- // bytes. If this panics then the scope guard will clear the
1643
- // table, leaking any elements that were not dropped yet.
1644
- //
1645
- // This leak is unavoidable: we can't try dropping more elements
1646
- // since this could lead to another panic and abort the process.
1647
- self_.drop_elements();
1648
-
1649
- // If necessary, resize our table to match the source.
1650
- if self_.buckets() != source.buckets() {
1651
- // Skip our drop by using ptr::write.
1652
- if !self_.table.is_empty_singleton() {
1653
- self_.free_buckets();
1654
- }
1655
- (&mut **self_ as *mut Self).write(
1656
- // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
1657
- match Self::new_uninitialized(
1658
- self_.table.alloc.clone(),
1659
- source.buckets(),
1660
- Fallibility::Infallible,
1661
- ) {
1662
- Ok(table) => table,
1663
- Err(_) => hint::unreachable_unchecked(),
1664
- },
1665
- );
1666
- }
1667
-
1668
- self_.clone_from_spec(source);
1669
-
1670
- // Disarm the scope guard if cloning was successful.
1671
- ScopeGuard::into_inner(self_);
1672
- }
1673
- }
1674
- }
1675
- }
1676
-
1677
- /// Specialization of `clone_from` for `Copy` types
1678
- trait RawTableClone {
1679
- unsafe fn clone_from_spec(&mut self, source: &Self);
1680
- }
1681
- impl<T: Clone, A: Allocator + Clone> RawTableClone for RawTable<T, A> {
1682
- default_fn! {
1683
- #[cfg_attr(feature = "inline-more", inline)]
1684
- unsafe fn clone_from_spec(&mut self, source: &Self) {
1685
- self.clone_from_impl(source);
1686
- }
1687
- }
1688
- }
1689
- #[cfg(feature = "nightly")]
1690
- impl<T: Copy, A: Allocator + Clone> RawTableClone for RawTable<T, A> {
1691
- #[cfg_attr(feature = "inline-more", inline)]
1692
- unsafe fn clone_from_spec(&mut self, source: &Self) {
1693
- source
1694
- .table
1695
- .ctrl(0)
1696
- .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes());
1697
- source
1698
- .data_start()
1699
- .copy_to_nonoverlapping(self.data_start(), self.table.buckets());
1700
-
1701
- self.table.items = source.table.items;
1702
- self.table.growth_left = source.table.growth_left;
1703
- }
1704
- }
1705
-
1706
- impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
1707
- /// Common code for clone and clone_from. Assumes:
1708
- /// - `self.buckets() == source.buckets()`.
1709
- /// - Any existing elements have been dropped.
1710
- /// - The control bytes are not initialized yet.
1711
- #[cfg_attr(feature = "inline-more", inline)]
1712
- unsafe fn clone_from_impl(&mut self, source: &Self) {
1713
- // Copy the control bytes unchanged. We do this in a single pass
1714
- source
1715
- .table
1716
- .ctrl(0)
1717
- .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes());
1718
-
1719
- // The cloning of elements may panic, in which case we need
1720
- // to make sure we drop only the elements that have been
1721
- // cloned so far.
1722
- let mut guard = guard((0, &mut *self), |(index, self_)| {
1723
- if mem::needs_drop::<T>() && !self_.is_empty() {
1724
- for i in 0..=*index {
1725
- if is_full(*self_.table.ctrl(i)) {
1726
- self_.bucket(i).drop();
1727
- }
1728
- }
1729
- }
1730
- });
1731
-
1732
- for from in source.iter() {
1733
- let index = source.bucket_index(&from);
1734
- let to = guard.1.bucket(index);
1735
- to.write(from.as_ref().clone());
1736
-
1737
- // Update the index in case we need to unwind.
1738
- guard.0 = index;
1739
- }
1740
-
1741
- // Successfully cloned all items, no need to clean up.
1742
- mem::forget(guard);
1743
-
1744
- self.table.items = source.table.items;
1745
- self.table.growth_left = source.table.growth_left;
1746
- }
1747
-
1748
- /// Variant of `clone_from` to use when a hasher is available.
1749
- #[cfg(feature = "raw")]
1750
- pub fn clone_from_with_hasher(&mut self, source: &Self, hasher: impl Fn(&T) -> u64) {
1751
- // If we have enough capacity in the table, just clear it and insert
1752
- // elements one by one. We don't do this if we have the same number of
1753
- // buckets as the source since we can just copy the contents directly
1754
- // in that case.
1755
- if self.table.buckets() != source.table.buckets()
1756
- && bucket_mask_to_capacity(self.table.bucket_mask) >= source.len()
1757
- {
1758
- self.clear();
1759
-
1760
- let guard_self = guard(&mut *self, |self_| {
1761
- // Clear the partially copied table if a panic occurs, otherwise
1762
- // items and growth_left will be out of sync with the contents
1763
- // of the table.
1764
- self_.clear();
1765
- });
1766
-
1767
- unsafe {
1768
- for item in source.iter() {
1769
- // This may panic.
1770
- let item = item.as_ref().clone();
1771
- let hash = hasher(&item);
1772
-
1773
- // We can use a simpler version of insert() here since:
1774
- // - there are no DELETED entries.
1775
- // - we know there is enough space in the table.
1776
- // - all elements are unique.
1777
- let (index, _) = guard_self.table.prepare_insert_slot(hash);
1778
- guard_self.bucket(index).write(item);
1779
- }
1780
- }
1781
-
1782
- // Successfully cloned all items, no need to clean up.
1783
- mem::forget(guard_self);
1784
-
1785
- self.table.items = source.table.items;
1786
- self.table.growth_left -= source.table.items;
1787
- } else {
1788
- self.clone_from(source);
1789
- }
1790
- }
1791
- }
1792
-
1793
- impl<T, A: Allocator + Clone + Default> Default for RawTable<T, A> {
1794
- #[inline]
1795
- fn default() -> Self {
1796
- Self::new_in(Default::default())
1797
- }
1798
- }
1799
-
1800
- #[cfg(feature = "nightly")]
1801
- unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawTable<T, A> {
1802
- #[cfg_attr(feature = "inline-more", inline)]
1803
- fn drop(&mut self) {
1804
- if !self.table.is_empty_singleton() {
1805
- unsafe {
1806
- self.drop_elements();
1807
- self.free_buckets();
1808
- }
1809
- }
1810
- }
1811
- }
1812
- #[cfg(not(feature = "nightly"))]
1813
- impl<T, A: Allocator + Clone> Drop for RawTable<T, A> {
1814
- #[cfg_attr(feature = "inline-more", inline)]
1815
- fn drop(&mut self) {
1816
- if !self.table.is_empty_singleton() {
1817
- unsafe {
1818
- self.drop_elements();
1819
- self.free_buckets();
1820
- }
1821
- }
1822
- }
1823
- }
1824
-
1825
- impl<T, A: Allocator + Clone> IntoIterator for RawTable<T, A> {
1826
- type Item = T;
1827
- type IntoIter = RawIntoIter<T, A>;
1828
-
1829
- #[cfg_attr(feature = "inline-more", inline)]
1830
- fn into_iter(self) -> RawIntoIter<T, A> {
1831
- unsafe {
1832
- let iter = self.iter();
1833
- self.into_iter_from(iter)
1834
- }
1835
- }
1836
- }
1837
-
1838
- /// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does
1839
- /// not track an item count.
1840
- pub(crate) struct RawIterRange<T> {
1841
- // Mask of full buckets in the current group. Bits are cleared from this
1842
- // mask as each element is processed.
1843
- current_group: BitMask,
1844
-
1845
- // Pointer to the buckets for the current group.
1846
- data: Bucket<T>,
1847
-
1848
- // Pointer to the next group of control bytes,
1849
- // Must be aligned to the group size.
1850
- next_ctrl: *const u8,
1851
-
1852
- // Pointer one past the last control byte of this range.
1853
- end: *const u8,
1854
- }
1855
-
1856
- impl<T> RawIterRange<T> {
1857
- /// Returns a `RawIterRange` covering a subset of a table.
1858
- ///
1859
- /// The control byte address must be aligned to the group size.
1860
- #[cfg_attr(feature = "inline-more", inline)]
1861
- unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self {
1862
- debug_assert_ne!(len, 0);
1863
- debug_assert_eq!(ctrl as usize % Group::WIDTH, 0);
1864
- let end = ctrl.add(len);
1865
-
1866
- // Load the first group and advance ctrl to point to the next group
1867
- let current_group = Group::load_aligned(ctrl).match_full();
1868
- let next_ctrl = ctrl.add(Group::WIDTH);
1869
-
1870
- Self {
1871
- current_group,
1872
- data,
1873
- next_ctrl,
1874
- end,
1875
- }
1876
- }
1877
-
1878
- /// Splits a `RawIterRange` into two halves.
1879
- ///
1880
- /// Returns `None` if the remaining range is smaller than or equal to the
1881
- /// group width.
1882
- #[cfg_attr(feature = "inline-more", inline)]
1883
- #[cfg(feature = "rayon")]
1884
- pub(crate) fn split(mut self) -> (Self, Option<RawIterRange<T>>) {
1885
- unsafe {
1886
- if self.end <= self.next_ctrl {
1887
- // Nothing to split if the group that we are current processing
1888
- // is the last one.
1889
- (self, None)
1890
- } else {
1891
- // len is the remaining number of elements after the group that
1892
- // we are currently processing. It must be a multiple of the
1893
- // group size (small tables are caught by the check above).
1894
- let len = offset_from(self.end, self.next_ctrl);
1895
- debug_assert_eq!(len % Group::WIDTH, 0);
1896
-
1897
- // Split the remaining elements into two halves, but round the
1898
- // midpoint down in case there is an odd number of groups
1899
- // remaining. This ensures that:
1900
- // - The tail is at least 1 group long.
1901
- // - The split is roughly even considering we still have the
1902
- // current group to process.
1903
- let mid = (len / 2) & !(Group::WIDTH - 1);
1904
-
1905
- let tail = Self::new(
1906
- self.next_ctrl.add(mid),
1907
- self.data.next_n(Group::WIDTH).next_n(mid),
1908
- len - mid,
1909
- );
1910
- debug_assert_eq!(
1911
- self.data.next_n(Group::WIDTH).next_n(mid).ptr,
1912
- tail.data.ptr
1913
- );
1914
- debug_assert_eq!(self.end, tail.end);
1915
- self.end = self.next_ctrl.add(mid);
1916
- debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl);
1917
- (self, Some(tail))
1918
- }
1919
- }
1920
- }
1921
-
1922
- /// # Safety
1923
- /// If DO_CHECK_PTR_RANGE is false, caller must ensure that we never try to iterate
1924
- /// after yielding all elements.
1925
- #[cfg_attr(feature = "inline-more", inline)]
1926
- unsafe fn next_impl<const DO_CHECK_PTR_RANGE: bool>(&mut self) -> Option<Bucket<T>> {
1927
- loop {
1928
- if let Some(index) = self.current_group.lowest_set_bit() {
1929
- self.current_group = self.current_group.remove_lowest_bit();
1930
- return Some(self.data.next_n(index));
1931
- }
1932
-
1933
- if DO_CHECK_PTR_RANGE && self.next_ctrl >= self.end {
1934
- return None;
1935
- }
1936
-
1937
- // We might read past self.end up to the next group boundary,
1938
- // but this is fine because it only occurs on tables smaller
1939
- // than the group size where the trailing control bytes are all
1940
- // EMPTY. On larger tables self.end is guaranteed to be aligned
1941
- // to the group size (since tables are power-of-two sized).
1942
- self.current_group = Group::load_aligned(self.next_ctrl).match_full();
1943
- self.data = self.data.next_n(Group::WIDTH);
1944
- self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
1945
- }
1946
- }
1947
- }
1948
-
1949
- // We make raw iterators unconditionally Send and Sync, and let the PhantomData
1950
- // in the actual iterator implementations determine the real Send/Sync bounds.
1951
- unsafe impl<T> Send for RawIterRange<T> {}
1952
- unsafe impl<T> Sync for RawIterRange<T> {}
1953
-
1954
- impl<T> Clone for RawIterRange<T> {
1955
- #[cfg_attr(feature = "inline-more", inline)]
1956
- fn clone(&self) -> Self {
1957
- Self {
1958
- data: self.data.clone(),
1959
- next_ctrl: self.next_ctrl,
1960
- current_group: self.current_group,
1961
- end: self.end,
1962
- }
1963
- }
1964
- }
1965
-
1966
- impl<T> Iterator for RawIterRange<T> {
1967
- type Item = Bucket<T>;
1968
-
1969
- #[cfg_attr(feature = "inline-more", inline)]
1970
- fn next(&mut self) -> Option<Bucket<T>> {
1971
- unsafe {
1972
- // SAFETY: We set checker flag to true.
1973
- self.next_impl::<true>()
1974
- }
1975
- }
1976
-
1977
- #[inline]
1978
- fn size_hint(&self) -> (usize, Option<usize>) {
1979
- // We don't have an item count, so just guess based on the range size.
1980
- let remaining_buckets = if self.end > self.next_ctrl {
1981
- unsafe { offset_from(self.end, self.next_ctrl) }
1982
- } else {
1983
- 0
1984
- };
1985
-
1986
- // Add a group width to include the group we are currently processing.
1987
- (0, Some(Group::WIDTH + remaining_buckets))
1988
- }
1989
- }
1990
-
1991
- impl<T> FusedIterator for RawIterRange<T> {}
1992
-
1993
- /// Iterator which returns a raw pointer to every full bucket in the table.
1994
- ///
1995
- /// For maximum flexibility this iterator is not bound by a lifetime, but you
1996
- /// must observe several rules when using it:
1997
- /// - You must not free the hash table while iterating (including via growing/shrinking).
1998
- /// - It is fine to erase a bucket that has been yielded by the iterator.
1999
- /// - Erasing a bucket that has not yet been yielded by the iterator may still
2000
- /// result in the iterator yielding that bucket (unless `reflect_remove` is called).
2001
- /// - It is unspecified whether an element inserted after the iterator was
2002
- /// created will be yielded by that iterator (unless `reflect_insert` is called).
2003
- /// - The order in which the iterator yields bucket is unspecified and may
2004
- /// change in the future.
2005
- pub struct RawIter<T> {
2006
- pub(crate) iter: RawIterRange<T>,
2007
- items: usize,
2008
- }
2009
-
2010
- impl<T> RawIter<T> {
2011
- /// Refresh the iterator so that it reflects a removal from the given bucket.
2012
- ///
2013
- /// For the iterator to remain valid, this method must be called once
2014
- /// for each removed bucket before `next` is called again.
2015
- ///
2016
- /// This method should be called _before_ the removal is made. It is not necessary to call this
2017
- /// method if you are removing an item that this iterator yielded in the past.
2018
- #[cfg(feature = "raw")]
2019
- pub fn reflect_remove(&mut self, b: &Bucket<T>) {
2020
- self.reflect_toggle_full(b, false);
2021
- }
2022
-
2023
- /// Refresh the iterator so that it reflects an insertion into the given bucket.
2024
- ///
2025
- /// For the iterator to remain valid, this method must be called once
2026
- /// for each insert before `next` is called again.
2027
- ///
2028
- /// This method does not guarantee that an insertion of a bucket with a greater
2029
- /// index than the last one yielded will be reflected in the iterator.
2030
- ///
2031
- /// This method should be called _after_ the given insert is made.
2032
- #[cfg(feature = "raw")]
2033
- pub fn reflect_insert(&mut self, b: &Bucket<T>) {
2034
- self.reflect_toggle_full(b, true);
2035
- }
2036
-
2037
- /// Refresh the iterator so that it reflects a change to the state of the given bucket.
2038
- #[cfg(feature = "raw")]
2039
- fn reflect_toggle_full(&mut self, b: &Bucket<T>, is_insert: bool) {
2040
- unsafe {
2041
- if b.as_ptr() > self.iter.data.as_ptr() {
2042
- // The iterator has already passed the bucket's group.
2043
- // So the toggle isn't relevant to this iterator.
2044
- return;
2045
- }
2046
-
2047
- if self.iter.next_ctrl < self.iter.end
2048
- && b.as_ptr() <= self.iter.data.next_n(Group::WIDTH).as_ptr()
2049
- {
2050
- // The iterator has not yet reached the bucket's group.
2051
- // We don't need to reload anything, but we do need to adjust the item count.
2052
-
2053
- if cfg!(debug_assertions) {
2054
- // Double-check that the user isn't lying to us by checking the bucket state.
2055
- // To do that, we need to find its control byte. We know that self.iter.data is
2056
- // at self.iter.next_ctrl - Group::WIDTH, so we work from there:
2057
- let offset = offset_from(self.iter.data.as_ptr(), b.as_ptr());
2058
- let ctrl = self.iter.next_ctrl.sub(Group::WIDTH).add(offset);
2059
- // This method should be called _before_ a removal, or _after_ an insert,
2060
- // so in both cases the ctrl byte should indicate that the bucket is full.
2061
- assert!(is_full(*ctrl));
2062
- }
2063
-
2064
- if is_insert {
2065
- self.items += 1;
2066
- } else {
2067
- self.items -= 1;
2068
- }
2069
-
2070
- return;
2071
- }
2072
-
2073
- // The iterator is at the bucket group that the toggled bucket is in.
2074
- // We need to do two things:
2075
- //
2076
- // - Determine if the iterator already yielded the toggled bucket.
2077
- // If it did, we're done.
2078
- // - Otherwise, update the iterator cached group so that it won't
2079
- // yield a to-be-removed bucket, or _will_ yield a to-be-added bucket.
2080
- // We'll also need to update the item count accordingly.
2081
- if let Some(index) = self.iter.current_group.lowest_set_bit() {
2082
- let next_bucket = self.iter.data.next_n(index);
2083
- if b.as_ptr() > next_bucket.as_ptr() {
2084
- // The toggled bucket is "before" the bucket the iterator would yield next. We
2085
- // therefore don't need to do anything --- the iterator has already passed the
2086
- // bucket in question.
2087
- //
2088
- // The item count must already be correct, since a removal or insert "prior" to
2089
- // the iterator's position wouldn't affect the item count.
2090
- } else {
2091
- // The removed bucket is an upcoming bucket. We need to make sure it does _not_
2092
- // get yielded, and also that it's no longer included in the item count.
2093
- //
2094
- // NOTE: We can't just reload the group here, both since that might reflect
2095
- // inserts we've already passed, and because that might inadvertently unset the
2096
- // bits for _other_ removals. If we do that, we'd have to also decrement the
2097
- // item count for those other bits that we unset. But the presumably subsequent
2098
- // call to reflect for those buckets might _also_ decrement the item count.
2099
- // Instead, we _just_ flip the bit for the particular bucket the caller asked
2100
- // us to reflect.
2101
- let our_bit = offset_from(self.iter.data.as_ptr(), b.as_ptr());
2102
- let was_full = self.iter.current_group.flip(our_bit);
2103
- debug_assert_ne!(was_full, is_insert);
2104
-
2105
- if is_insert {
2106
- self.items += 1;
2107
- } else {
2108
- self.items -= 1;
2109
- }
2110
-
2111
- if cfg!(debug_assertions) {
2112
- if b.as_ptr() == next_bucket.as_ptr() {
2113
- // The removed bucket should no longer be next
2114
- debug_assert_ne!(self.iter.current_group.lowest_set_bit(), Some(index));
2115
- } else {
2116
- // We should not have changed what bucket comes next.
2117
- debug_assert_eq!(self.iter.current_group.lowest_set_bit(), Some(index));
2118
- }
2119
- }
2120
- }
2121
- } else {
2122
- // We must have already iterated past the removed item.
2123
- }
2124
- }
2125
- }
2126
-
2127
- unsafe fn drop_elements(&mut self) {
2128
- if mem::needs_drop::<T>() && self.len() != 0 {
2129
- for item in self {
2130
- item.drop();
2131
- }
2132
- }
2133
- }
2134
- }
2135
-
2136
- impl<T> Clone for RawIter<T> {
2137
- #[cfg_attr(feature = "inline-more", inline)]
2138
- fn clone(&self) -> Self {
2139
- Self {
2140
- iter: self.iter.clone(),
2141
- items: self.items,
2142
- }
2143
- }
2144
- }
2145
-
2146
- impl<T> Iterator for RawIter<T> {
2147
- type Item = Bucket<T>;
2148
-
2149
- #[cfg_attr(feature = "inline-more", inline)]
2150
- fn next(&mut self) -> Option<Bucket<T>> {
2151
- // Inner iterator iterates over buckets
2152
- // so it can do unnecessary work if we already yielded all items.
2153
- if self.items == 0 {
2154
- return None;
2155
- }
2156
-
2157
- let nxt = unsafe {
2158
- // SAFETY: We check number of items to yield using `items` field.
2159
- self.iter.next_impl::<false>()
2160
- };
2161
-
2162
- if nxt.is_some() {
2163
- self.items -= 1;
2164
- }
2165
-
2166
- nxt
2167
- }
2168
-
2169
- #[inline]
2170
- fn size_hint(&self) -> (usize, Option<usize>) {
2171
- (self.items, Some(self.items))
2172
- }
2173
- }
2174
-
2175
- impl<T> ExactSizeIterator for RawIter<T> {}
2176
- impl<T> FusedIterator for RawIter<T> {}
2177
-
2178
- /// Iterator which consumes a table and returns elements.
2179
- pub struct RawIntoIter<T, A: Allocator + Clone = Global> {
2180
- iter: RawIter<T>,
2181
- allocation: Option<(NonNull<u8>, Layout)>,
2182
- marker: PhantomData<T>,
2183
- alloc: A,
2184
- }
2185
-
2186
- impl<T, A: Allocator + Clone> RawIntoIter<T, A> {
2187
- #[cfg_attr(feature = "inline-more", inline)]
2188
- pub fn iter(&self) -> RawIter<T> {
2189
- self.iter.clone()
2190
- }
2191
- }
2192
-
2193
- unsafe impl<T, A: Allocator + Clone> Send for RawIntoIter<T, A>
2194
- where
2195
- T: Send,
2196
- A: Send,
2197
- {
2198
- }
2199
- unsafe impl<T, A: Allocator + Clone> Sync for RawIntoIter<T, A>
2200
- where
2201
- T: Sync,
2202
- A: Sync,
2203
- {
2204
- }
2205
-
2206
- #[cfg(feature = "nightly")]
2207
- unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
2208
- #[cfg_attr(feature = "inline-more", inline)]
2209
- fn drop(&mut self) {
2210
- unsafe {
2211
- // Drop all remaining elements
2212
- self.iter.drop_elements();
2213
-
2214
- // Free the table
2215
- if let Some((ptr, layout)) = self.allocation {
2216
- self.alloc.deallocate(ptr, layout);
2217
- }
2218
- }
2219
- }
2220
- }
2221
- #[cfg(not(feature = "nightly"))]
2222
- impl<T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {
2223
- #[cfg_attr(feature = "inline-more", inline)]
2224
- fn drop(&mut self) {
2225
- unsafe {
2226
- // Drop all remaining elements
2227
- self.iter.drop_elements();
2228
-
2229
- // Free the table
2230
- if let Some((ptr, layout)) = self.allocation {
2231
- self.alloc.deallocate(ptr, layout);
2232
- }
2233
- }
2234
- }
2235
- }
2236
-
2237
- impl<T, A: Allocator + Clone> Iterator for RawIntoIter<T, A> {
2238
- type Item = T;
2239
-
2240
- #[cfg_attr(feature = "inline-more", inline)]
2241
- fn next(&mut self) -> Option<T> {
2242
- unsafe { Some(self.iter.next()?.read()) }
2243
- }
2244
-
2245
- #[inline]
2246
- fn size_hint(&self) -> (usize, Option<usize>) {
2247
- self.iter.size_hint()
2248
- }
2249
- }
2250
-
2251
- impl<T, A: Allocator + Clone> ExactSizeIterator for RawIntoIter<T, A> {}
2252
- impl<T, A: Allocator + Clone> FusedIterator for RawIntoIter<T, A> {}
2253
-
2254
- /// Iterator which consumes elements without freeing the table storage.
2255
- pub struct RawDrain<'a, T, A: Allocator + Clone = Global> {
2256
- iter: RawIter<T>,
2257
-
2258
- // The table is moved into the iterator for the duration of the drain. This
2259
- // ensures that an empty table is left if the drain iterator is leaked
2260
- // without dropping.
2261
- table: ManuallyDrop<RawTable<T, A>>,
2262
- orig_table: NonNull<RawTable<T, A>>,
2263
-
2264
- // We don't use a &'a mut RawTable<T> because we want RawDrain to be
2265
- // covariant over T.
2266
- marker: PhantomData<&'a RawTable<T, A>>,
2267
- }
2268
-
2269
- impl<T, A: Allocator + Clone> RawDrain<'_, T, A> {
2270
- #[cfg_attr(feature = "inline-more", inline)]
2271
- pub fn iter(&self) -> RawIter<T> {
2272
- self.iter.clone()
2273
- }
2274
- }
2275
-
2276
- unsafe impl<T, A: Allocator + Copy> Send for RawDrain<'_, T, A>
2277
- where
2278
- T: Send,
2279
- A: Send,
2280
- {
2281
- }
2282
- unsafe impl<T, A: Allocator + Copy> Sync for RawDrain<'_, T, A>
2283
- where
2284
- T: Sync,
2285
- A: Sync,
2286
- {
2287
- }
2288
-
2289
- impl<T, A: Allocator + Clone> Drop for RawDrain<'_, T, A> {
2290
- #[cfg_attr(feature = "inline-more", inline)]
2291
- fn drop(&mut self) {
2292
- unsafe {
2293
- // Drop all remaining elements. Note that this may panic.
2294
- self.iter.drop_elements();
2295
-
2296
- // Reset the contents of the table now that all elements have been
2297
- // dropped.
2298
- self.table.clear_no_drop();
2299
-
2300
- // Move the now empty table back to its original location.
2301
- self.orig_table
2302
- .as_ptr()
2303
- .copy_from_nonoverlapping(&*self.table, 1);
2304
- }
2305
- }
2306
- }
2307
-
2308
- impl<T, A: Allocator + Clone> Iterator for RawDrain<'_, T, A> {
2309
- type Item = T;
2310
-
2311
- #[cfg_attr(feature = "inline-more", inline)]
2312
- fn next(&mut self) -> Option<T> {
2313
- unsafe {
2314
- let item = self.iter.next()?;
2315
- Some(item.read())
2316
- }
2317
- }
2318
-
2319
- #[inline]
2320
- fn size_hint(&self) -> (usize, Option<usize>) {
2321
- self.iter.size_hint()
2322
- }
2323
- }
2324
-
2325
- impl<T, A: Allocator + Clone> ExactSizeIterator for RawDrain<'_, T, A> {}
2326
- impl<T, A: Allocator + Clone> FusedIterator for RawDrain<'_, T, A> {}
2327
-
2328
- /// Iterator over occupied buckets that could match a given hash.
2329
- ///
2330
- /// `RawTable` only stores 7 bits of the hash value, so this iterator may return
2331
- /// items that have a hash value different than the one provided. You should
2332
- /// always validate the returned values before using them.
2333
- pub struct RawIterHash<'a, T, A: Allocator + Clone = Global> {
2334
- inner: RawIterHashInner<'a, A>,
2335
- _marker: PhantomData<T>,
2336
- }
2337
-
2338
- struct RawIterHashInner<'a, A: Allocator + Clone> {
2339
- table: &'a RawTableInner<A>,
2340
-
2341
- // The top 7 bits of the hash.
2342
- h2_hash: u8,
2343
-
2344
- // The sequence of groups to probe in the search.
2345
- probe_seq: ProbeSeq,
2346
-
2347
- group: Group,
2348
-
2349
- // The elements within the group with a matching h2-hash.
2350
- bitmask: BitMaskIter,
2351
- }
2352
-
2353
- impl<'a, T, A: Allocator + Clone> RawIterHash<'a, T, A> {
2354
- #[cfg_attr(feature = "inline-more", inline)]
2355
- #[cfg(feature = "raw")]
2356
- fn new(table: &'a RawTable<T, A>, hash: u64) -> Self {
2357
- RawIterHash {
2358
- inner: RawIterHashInner::new(&table.table, hash),
2359
- _marker: PhantomData,
2360
- }
2361
- }
2362
- }
2363
- impl<'a, A: Allocator + Clone> RawIterHashInner<'a, A> {
2364
- #[cfg_attr(feature = "inline-more", inline)]
2365
- #[cfg(feature = "raw")]
2366
- fn new(table: &'a RawTableInner<A>, hash: u64) -> Self {
2367
- unsafe {
2368
- let h2_hash = h2(hash);
2369
- let probe_seq = table.probe_seq(hash);
2370
- let group = Group::load(table.ctrl(probe_seq.pos));
2371
- let bitmask = group.match_byte(h2_hash).into_iter();
2372
-
2373
- RawIterHashInner {
2374
- table,
2375
- h2_hash,
2376
- probe_seq,
2377
- group,
2378
- bitmask,
2379
- }
2380
- }
2381
- }
2382
- }
2383
-
2384
- impl<'a, T, A: Allocator + Clone> Iterator for RawIterHash<'a, T, A> {
2385
- type Item = Bucket<T>;
2386
-
2387
- fn next(&mut self) -> Option<Bucket<T>> {
2388
- unsafe {
2389
- match self.inner.next() {
2390
- Some(index) => Some(self.inner.table.bucket(index)),
2391
- None => None,
2392
- }
2393
- }
2394
- }
2395
- }
2396
-
2397
- impl<'a, A: Allocator + Clone> Iterator for RawIterHashInner<'a, A> {
2398
- type Item = usize;
2399
-
2400
- fn next(&mut self) -> Option<Self::Item> {
2401
- unsafe {
2402
- loop {
2403
- if let Some(bit) = self.bitmask.next() {
2404
- let index = (self.probe_seq.pos + bit) & self.table.bucket_mask;
2405
- return Some(index);
2406
- }
2407
- if likely(self.group.match_empty().any_bit_set()) {
2408
- return None;
2409
- }
2410
- self.probe_seq.move_next(self.table.bucket_mask);
2411
- self.group = Group::load(self.table.ctrl(self.probe_seq.pos));
2412
- self.bitmask = self.group.match_byte(self.h2_hash).into_iter();
2413
- }
2414
- }
2415
- }
2416
- }
2417
-
2418
- #[cfg(test)]
2419
- mod test_map {
2420
- use super::*;
2421
-
2422
- fn rehash_in_place<T>(table: &mut RawTable<T>, hasher: impl Fn(&T) -> u64) {
2423
- unsafe {
2424
- table.table.rehash_in_place(
2425
- &|table, index| hasher(table.bucket::<T>(index).as_ref()),
2426
- mem::size_of::<T>(),
2427
- if mem::needs_drop::<T>() {
2428
- Some(mem::transmute(ptr::drop_in_place::<T> as unsafe fn(*mut T)))
2429
- } else {
2430
- None
2431
- },
2432
- );
2433
- }
2434
- }
2435
-
2436
- #[test]
2437
- fn rehash() {
2438
- let mut table = RawTable::new();
2439
- let hasher = |i: &u64| *i;
2440
- for i in 0..100 {
2441
- table.insert(i, i, hasher);
2442
- }
2443
-
2444
- for i in 0..100 {
2445
- unsafe {
2446
- assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i));
2447
- }
2448
- assert!(table.find(i + 100, |x| *x == i + 100).is_none());
2449
- }
2450
-
2451
- rehash_in_place(&mut table, hasher);
2452
-
2453
- for i in 0..100 {
2454
- unsafe {
2455
- assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i));
2456
- }
2457
- assert!(table.find(i + 100, |x| *x == i + 100).is_none());
2458
- }
2459
- }
2460
- }