fastquadtree 2.2.0__tar.gz → 2.3.0__tar.gz

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 (115) hide show
  1. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/Cargo.lock +82 -48
  2. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/Cargo.toml +3 -3
  3. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/LICENSE +1 -1
  4. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/PKG-INFO +6 -2
  5. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/README.md +5 -1
  6. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/2.0_migration_guide.md +3 -1
  7. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/benchmark.md +9 -9
  8. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/index.md +2 -2
  9. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_base_quadtree.py +40 -5
  10. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_base_quadtree_objects.py +39 -5
  11. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_common.py +41 -3
  12. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/point_quadtree.py +10 -2
  13. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/point_quadtree_objects.py +10 -2
  14. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/rect_quadtree.py +10 -2
  15. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/rect_quadtree_objects.py +10 -2
  16. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/src/geom.rs +6 -8
  17. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/src/lib.rs +26 -4
  18. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/src/quadtree.rs +40 -12
  19. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/src/rect_quadtree.rs +42 -14
  20. fastquadtree-2.3.0/src/serialization.rs +258 -0
  21. fastquadtree-2.3.0/tests/serialization.rs +151 -0
  22. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/common/test_internal_edges.py +26 -5
  23. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points/test_point_quadtree_serialization.py +53 -1
  24. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points_objects/test_point_quadtree_objects_serialization.py +27 -1
  25. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects/test_rect_quadtree_serialization.py +34 -1
  26. fastquadtree-2.2.0/tests/serialization.rs +0 -63
  27. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/.github/workflows/docs.yml +0 -0
  28. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/.github/workflows/release.yml +0 -0
  29. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/.github/workflows/test.yml +0 -0
  30. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/.gitignore +0 -0
  31. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/.pre-commit-config.yaml +0 -0
  32. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/ballpit.png +0 -0
  33. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/interactive_v2_rect_screenshot.png +0 -0
  34. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/interactive_v2_screenshot.png +0 -0
  35. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/pygame_sprites_demo.png +0 -0
  36. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/quadtree_bench_throughput.png +0 -0
  37. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/assets/quadtree_bench_time.png +0 -0
  38. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/benchmark_native_vs_shim.py +0 -0
  39. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/benchmark_np_vs_list.py +0 -0
  40. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/benchmark_serialization_vs_rebuild.py +0 -0
  41. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/cross_library_bench.py +0 -0
  42. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/__init__.py +0 -0
  43. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/engines.py +0 -0
  44. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/main.py +0 -0
  45. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/optimizer.py +0 -0
  46. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/plotting.py +0 -0
  47. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/quadtree_bench/runner.py +0 -0
  48. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/runner.py +0 -0
  49. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/benchmarks/system_info_collector.py +0 -0
  50. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/2.0_proposal.md +0 -0
  51. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/insert_result.md +0 -0
  52. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/item.md +0 -0
  53. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/point_item.md +0 -0
  54. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/pygame.md +0 -0
  55. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/pyqtree.md +0 -0
  56. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/quadtree.md +0 -0
  57. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/quadtree_objects.md +0 -0
  58. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/rect_item.md +0 -0
  59. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/rect_quadtree.md +0 -0
  60. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/api/rect_quadtree_objects.md +0 -0
  61. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/future_features.md +0 -0
  62. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/quickstart.md +0 -0
  63. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/runnables.md +0 -0
  64. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/rust_usage.md +0 -0
  65. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/docs/styles/overrides.css +0 -0
  66. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/examples/custom_id_example.py +0 -0
  67. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/examples/object_tracking_example.py +0 -0
  68. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/interactive/ballpit.py +0 -0
  69. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/interactive/interactive.py +0 -0
  70. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/interactive/interactive_v2.py +0 -0
  71. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/interactive/interactive_v2_rect.py +0 -0
  72. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/interactive/pygame_sprites.py +0 -0
  73. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/mkdocs.yml +0 -0
  74. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pyproject.toml +0 -0
  75. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pyrightconfig.json +0 -0
  76. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/__init__.py +0 -0
  77. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_insert_result.py +0 -0
  78. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_item.py +0 -0
  79. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/_obj_store.py +0 -0
  80. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/py.typed +0 -0
  81. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/pygame.py +0 -0
  82. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/pysrc/fastquadtree/pyqtree.py +0 -0
  83. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/__init__.py +0 -0
  84. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/insertions.rs +0 -0
  85. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/nearest_neighbor.rs +0 -0
  86. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/query.rs +0 -0
  87. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/rect_quadtree.rs +0 -0
  88. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/rectangle_traversal.rs +0 -0
  89. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_delete.rs +0 -0
  90. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/__init__.py +0 -0
  91. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/common/test_common_validation.py +0 -0
  92. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/common/test_insert_result_and_items.py +0 -0
  93. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/common/test_obj_store.py +0 -0
  94. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/common/test_serialization_container.py +0 -0
  95. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/conftest.py +0 -0
  96. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/integration/test_migration_breaks_and_safety.py +0 -0
  97. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/integration/test_optional_pygame_dependency.py +0 -0
  98. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/integration/test_public_api_contracts.py +0 -0
  99. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/integration/test_pygame_integration.py +0 -0
  100. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points/test_point_quadtree_core.py +0 -0
  101. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points/test_point_quadtree_mutation.py +0 -0
  102. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points/test_point_quadtree_numpy.py +0 -0
  103. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points/test_point_quadtree_precision.py +0 -0
  104. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points_objects/test_point_quadtree_objects_core.py +0 -0
  105. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points_objects/test_point_quadtree_objects_deletion_update.py +0 -0
  106. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/points_objects/test_point_quadtree_objects_numpy.py +0 -0
  107. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects/test_rect_quadtree_core.py +0 -0
  108. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects/test_rect_quadtree_mutation.py +0 -0
  109. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects/test_rect_quadtree_numpy.py +0 -0
  110. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_core.py +0 -0
  111. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_deletion_update.py +0 -0
  112. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_numpy.py +0 -0
  113. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/rects_objects/test_rect_quadtree_objects_serialization.py +0 -0
  114. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/test_python/test_pyqtree_shim_compat.py +0 -0
  115. {fastquadtree-2.2.0 → fastquadtree-2.3.0}/tests/unconventional_bounds.rs +0 -0
@@ -9,35 +9,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
9
9
  checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
10
10
 
11
11
  [[package]]
12
- name = "bincode"
13
- version = "2.0.1"
12
+ name = "darling"
13
+ version = "0.23.0"
14
14
  source = "registry+https://github.com/rust-lang/crates.io-index"
15
- checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
15
+ checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
16
16
  dependencies = [
17
- "bincode_derive",
18
- "serde",
19
- "unty",
17
+ "darling_core",
18
+ "darling_macro",
20
19
  ]
21
20
 
22
21
  [[package]]
23
- name = "bincode_derive"
24
- version = "2.0.1"
22
+ name = "darling_core"
23
+ version = "0.23.0"
25
24
  source = "registry+https://github.com/rust-lang/crates.io-index"
26
- checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
25
+ checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
27
26
  dependencies = [
28
- "virtue",
27
+ "ident_case",
28
+ "proc-macro2",
29
+ "quote",
30
+ "strsim",
31
+ "syn",
32
+ ]
33
+
34
+ [[package]]
35
+ name = "darling_macro"
36
+ version = "0.23.0"
37
+ source = "registry+https://github.com/rust-lang/crates.io-index"
38
+ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
39
+ dependencies = [
40
+ "darling_core",
41
+ "quote",
42
+ "syn",
29
43
  ]
30
44
 
31
45
  [[package]]
32
46
  name = "fastquadtree"
33
- version = "2.2.0"
47
+ version = "2.3.0"
34
48
  dependencies = [
35
- "bincode",
36
49
  "num-traits",
37
50
  "numpy",
38
51
  "pyo3",
39
- "serde",
40
52
  "smallvec",
53
+ "wincode",
41
54
  ]
42
55
 
43
56
  [[package]]
@@ -46,6 +59,12 @@ version = "0.5.0"
46
59
  source = "registry+https://github.com/rust-lang/crates.io-index"
47
60
  checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
48
61
 
62
+ [[package]]
63
+ name = "ident_case"
64
+ version = "1.0.1"
65
+ source = "registry+https://github.com/rust-lang/crates.io-index"
66
+ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
67
+
49
68
  [[package]]
50
69
  name = "libc"
51
70
  version = "0.2.186"
@@ -126,6 +145,12 @@ version = "1.21.4"
126
145
  source = "registry+https://github.com/rust-lang/crates.io-index"
127
146
  checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
128
147
 
148
+ [[package]]
149
+ name = "pastey"
150
+ version = "0.2.3"
151
+ source = "registry+https://github.com/rust-lang/crates.io-index"
152
+ checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
153
+
129
154
  [[package]]
130
155
  name = "portable-atomic"
131
156
  version = "1.13.1"
@@ -230,57 +255,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
230
255
  checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
231
256
 
232
257
  [[package]]
233
- name = "serde"
234
- version = "1.0.228"
258
+ name = "smallvec"
259
+ version = "1.15.1"
235
260
  source = "registry+https://github.com/rust-lang/crates.io-index"
236
- checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
237
- dependencies = [
238
- "serde_core",
239
- "serde_derive",
240
- ]
261
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
241
262
 
242
263
  [[package]]
243
- name = "serde_core"
244
- version = "1.0.228"
264
+ name = "strsim"
265
+ version = "0.11.1"
245
266
  source = "registry+https://github.com/rust-lang/crates.io-index"
246
- checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
247
- dependencies = [
248
- "serde_derive",
249
- ]
267
+ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
250
268
 
251
269
  [[package]]
252
- name = "serde_derive"
253
- version = "1.0.228"
270
+ name = "syn"
271
+ version = "2.0.117"
254
272
  source = "registry+https://github.com/rust-lang/crates.io-index"
255
- checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
273
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
256
274
  dependencies = [
257
275
  "proc-macro2",
258
276
  "quote",
259
- "syn",
277
+ "unicode-ident",
260
278
  ]
261
279
 
262
280
  [[package]]
263
- name = "smallvec"
264
- version = "1.15.1"
281
+ name = "target-lexicon"
282
+ version = "0.13.5"
265
283
  source = "registry+https://github.com/rust-lang/crates.io-index"
266
- checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
284
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
267
285
 
268
286
  [[package]]
269
- name = "syn"
270
- version = "2.0.117"
287
+ name = "thiserror"
288
+ version = "2.0.18"
271
289
  source = "registry+https://github.com/rust-lang/crates.io-index"
272
- checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
290
+ checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
273
291
  dependencies = [
274
- "proc-macro2",
275
- "quote",
276
- "unicode-ident",
292
+ "thiserror-impl",
277
293
  ]
278
294
 
279
295
  [[package]]
280
- name = "target-lexicon"
281
- version = "0.13.5"
296
+ name = "thiserror-impl"
297
+ version = "2.0.18"
282
298
  source = "registry+https://github.com/rust-lang/crates.io-index"
283
- checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
299
+ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
300
+ dependencies = [
301
+ "proc-macro2",
302
+ "quote",
303
+ "syn",
304
+ ]
284
305
 
285
306
  [[package]]
286
307
  name = "unicode-ident"
@@ -289,13 +310,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
289
310
  checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
290
311
 
291
312
  [[package]]
292
- name = "unty"
293
- version = "0.0.4"
313
+ name = "wincode"
314
+ version = "0.5.5"
294
315
  source = "registry+https://github.com/rust-lang/crates.io-index"
295
- checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
316
+ checksum = "66d967db7705dc29120bb6e8ce5b5a2e27734ed5976d1c904e95bd238d1c3c5a"
317
+ dependencies = [
318
+ "pastey",
319
+ "proc-macro2",
320
+ "quote",
321
+ "thiserror",
322
+ "wincode-derive",
323
+ ]
296
324
 
297
325
  [[package]]
298
- name = "virtue"
299
- version = "0.0.18"
326
+ name = "wincode-derive"
327
+ version = "0.4.6"
300
328
  source = "registry+https://github.com/rust-lang/crates.io-index"
301
- checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
329
+ checksum = "15ab90b719560d0fda79c74550ad1c948d17b118765942838055ebaf34d67071"
330
+ dependencies = [
331
+ "darling",
332
+ "proc-macro2",
333
+ "quote",
334
+ "syn",
335
+ ]
@@ -1,7 +1,8 @@
1
1
  [package]
2
2
  name = "fastquadtree"
3
- version = "2.2.0"
3
+ version = "2.3.0"
4
4
  edition = "2021"
5
+ rust-version = "1.89"
5
6
  readme = "README.md"
6
7
 
7
8
  [lib]
@@ -11,8 +12,7 @@ crate-type = ["rlib", "cdylib"]
11
12
  pyo3 = { version = "0.28", features = ["extension-module", "abi3-py39"] }
12
13
  smallvec = "1.15.1"
13
14
  numpy = "0.28"
14
- serde = { version = "1.0", features = ["derive"] }
15
- bincode = {version = "2.0.1", features = ["serde"]}
15
+ wincode = { version = "0.5.5", features = ["derive"] }
16
16
  num-traits = "0.2"
17
17
 
18
18
  [profile.release]
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Ethan Anderson
3
+ Copyright (c) 2025-2026 Ethan Anderson
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Python :: 3.9
@@ -62,6 +62,7 @@ Rust-optimized quadtree with a clean Python API
62
62
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
63
63
  - Fast KNN and range queries
64
64
  - Optional object tracking for id ↔ object mapping
65
+ - Mostly drop-in [pygame sprite-group integration](https://elan456.github.io/fastquadtree/api/pygame/) that adds automatic broadphase culling for faster collision detection (depending on workload)
65
66
  - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
66
67
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
67
68
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -88,6 +89,7 @@ from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~10x faster whil
88
89
  | `QuadTreeObjects` | Points | Yes | Point indexing with attached Python objects. |
89
90
  | `RectQuadTreeObjects` | Bounding boxes | Yes | Rectangle indexing with attached objects. |
90
91
  | `fastquadtree.pyqtree.Index` | Bounding boxes | Yes | pyqtree-compatible API, much faster. |
92
+ | `fastquadtree.pygame.Group` | pygame sprites | Yes | Mostly drop-in replacement for `pygame.sprite.Group` with quadtree indexing for faster collision detection. |
91
93
 
92
94
 
93
95
  ## Quickstart
@@ -233,7 +235,9 @@ qt.insert_many_np(points) # Use insert_many_np for NumPy arrays
233
235
  ```
234
236
 
235
237
  **Does fastquadtree support multiprocessing?**
236
- Yes, fastquadtree objects can be serialized to bytes using the `to_bytes()` method and deserialized back using `from_bytes()`. This allows you to share quadtree data across processes and even cache prebuilt trees to disk. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. See the [interactive v2 demo](https://github.com/Elan456/fastquadtree/blob/main/interactive/interactive_v2.py) for an example of saving and loading a quadtree, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
238
+ Yes, fastquadtree objects can be serialized to bytes using the `to_bytes()` method and deserialized back using `from_bytes()`. This allows you to share quadtree data across processes and even cache prebuilt trees to disk. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. Native decode uses a default preallocation limit of 67,108,864 bytes (64 MiB); if loading needs more than the configured bucket, `from_bytes()` fails with a `ValueError` unless you choose a larger allowed bucket or pass `disable_preallocation_limit=True` for trusted data. See the [interactive v2 demo](https://github.com/Elan456/fastquadtree/blob/main/interactive/interactive_v2.py) for an example of saving and loading a quadtree, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
239
+
240
+ Serialization uses the current fastquadtree binary format. Data serialized by bincode-backed fastquadtree releases, including v2.2 and earlier, is not loadable by newer wincode-backed releases.
237
241
 
238
242
  ## License
239
243
 
@@ -32,6 +32,7 @@ Rust-optimized quadtree with a clean Python API
32
32
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
33
33
  - Fast KNN and range queries
34
34
  - Optional object tracking for id ↔ object mapping
35
+ - Mostly drop-in [pygame sprite-group integration](https://elan456.github.io/fastquadtree/api/pygame/) that adds automatic broadphase culling for faster collision detection (depending on workload)
35
36
  - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
36
37
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
37
38
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -58,6 +59,7 @@ from fastquadtree.pyqtree import Index # Drop-in pyqtree shim (~10x faster whil
58
59
  | `QuadTreeObjects` | Points | Yes | Point indexing with attached Python objects. |
59
60
  | `RectQuadTreeObjects` | Bounding boxes | Yes | Rectangle indexing with attached objects. |
60
61
  | `fastquadtree.pyqtree.Index` | Bounding boxes | Yes | pyqtree-compatible API, much faster. |
62
+ | `fastquadtree.pygame.Group` | pygame sprites | Yes | Mostly drop-in replacement for `pygame.sprite.Group` with quadtree indexing for faster collision detection. |
61
63
 
62
64
 
63
65
  ## Quickstart
@@ -203,7 +205,9 @@ qt.insert_many_np(points) # Use insert_many_np for NumPy arrays
203
205
  ```
204
206
 
205
207
  **Does fastquadtree support multiprocessing?**
206
- Yes, fastquadtree objects can be serialized to bytes using the `to_bytes()` method and deserialized back using `from_bytes()`. This allows you to share quadtree data across processes and even cache prebuilt trees to disk. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. See the [interactive v2 demo](https://github.com/Elan456/fastquadtree/blob/main/interactive/interactive_v2.py) for an example of saving and loading a quadtree, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
208
+ Yes, fastquadtree objects can be serialized to bytes using the `to_bytes()` method and deserialized back using `from_bytes()`. This allows you to share quadtree data across processes and even cache prebuilt trees to disk. When using `QuadTreeObjects` or `RectQuadTreeObjects`, you must pass `include_objects=True` to `to_bytes()` to serialize Python objects, and `allow_objects=True` to `from_bytes()` when loading. By default, objects are skipped for safety, as deserializing untrusted Python objects can be unsafe. Native decode uses a default preallocation limit of 67,108,864 bytes (64 MiB); if loading needs more than the configured bucket, `from_bytes()` fails with a `ValueError` unless you choose a larger allowed bucket or pass `disable_preallocation_limit=True` for trusted data. See the [interactive v2 demo](https://github.com/Elan456/fastquadtree/blob/main/interactive/interactive_v2.py) for an example of saving and loading a quadtree, and the [QuadTreeObjects API docs](https://elan456.github.io/fastquadtree/api/quadtree_objects/#fastquadtree.QuadTreeObjects.to_bytes) for full details on the serialization methods.
209
+
210
+ Serialization uses the current fastquadtree binary format. Data serialized by bincode-backed fastquadtree releases, including v2.2 and earlier, is not loadable by newer wincode-backed releases.
207
211
 
208
212
  ## License
209
213
 
@@ -288,6 +288,8 @@ rqt_obj.update(id_, new_min_x, new_min_y, new_max_x, new_max_y)
288
288
 
289
289
  The serialization format has changed. **v1 serialized data cannot be loaded in v2.**
290
290
 
291
+ The native core codec changed again after v2.2 from bincode to wincode. Bincode-backed serialized data from fastquadtree v2.2 and earlier is not loadable by newer wincode-backed releases.
292
+
291
293
  ### Before (v1.x)
292
294
 
293
295
  ```python
@@ -455,4 +457,4 @@ from fastquadtree import (
455
457
  PointItem,
456
458
  RectItem,
457
459
  )
458
- ```
460
+ ```
@@ -132,22 +132,22 @@ If your data is already in a NumPy array, using the `insert_many_np` method dire
132
132
 
133
133
  | Variant | Mean (s) | Stdev (s) |
134
134
  |---|---:|---:|
135
- | Serialize to bytes | 0.021356 | 0.000937 |
136
- | Rebuild from points | 0.106783 | 0.011430 |
137
- | Rebuild from bytes | 0.021754 | 0.001687 |
138
- | Rebuild from file | 0.024887 | 0.001846 |
135
+ | Serialize to bytes | 0.011789 | 0.000617 |
136
+ | Rebuild from points | 0.088791 | 0.001616 |
137
+ | Rebuild from bytes | 0.007105 | 0.000137 |
138
+ | Rebuild from file | 0.012052 | 0.000442 |
139
139
 
140
140
  ### Summary
141
141
 
142
- - Rebuild from bytes is **4.908747x** faster than reinserting points.
143
- - Rebuild from file is **4.290712x** faster than reinserting points.
144
- - Serialized blob size is **13,770,328 bytes**.
142
+ - Rebuild from bytes is **12.497145x** faster than reinserting points.
143
+ - Rebuild from file is **7.367322x** faster than reinserting points.
144
+ - Serialized blob size is **18,104,173 bytes**.
145
145
 
146
146
  ----------------
147
147
 
148
148
  ## System Info
149
- - **OS**: CachyOS 6.18.5-2-cachyos x86_64
150
- - **Python**: CPython 3.14.2
149
+ - **OS**: CachyOS 7.0.10-1-cachyos x86_64
150
+ - **Python**: CPython 3.14.5
151
151
  - **CPU**: AMD Ryzen 7 3700X 8-Core Processor (16 threads)
152
152
  - **Memory**: 31.3 GB
153
153
  - **GPU**: NVIDIA GeForce RTX 5070 (11.9 GB)
@@ -41,7 +41,7 @@
41
41
  - Support for [inserting bounding boxes](api/rect_quadtree.md) or points
42
42
  - Fast KNN and range queries
43
43
  - Optional object tracking for id ↔ object mapping
44
- - Drop-in [pygame sprite-group integration](api/pygame.md) that adds automatic broadphase culling for faster collision detection (depending on workload)
44
+ - Mostly drop-in [pygame sprite-group integration](api/pygame.md) that adds automatic broadphase culling for faster collision detection (depending on workload)
45
45
  - Fast [serialization](benchmark.md#serialization-vs-rebuild) to/from bytes
46
46
  - Support for multiple data types (f32, f64, i32, i64) for coordinates
47
47
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
@@ -63,5 +63,5 @@ from fastquadtree import RectQuadTree # Bounding box handling
63
63
  from fastquadtree import QuadTreeObjects # Point handling with object tracking
64
64
  from fastquadtree import RectQuadTreeObjects # Bounding box handling with object tracking
65
65
  from fastquadtree.pyqtree import Index # Drop-in replacement for pyqtree (~10x faster while keeping the same API)
66
- from fastquadtree.pygame import Group # Drop-in replacement for pygame.sprite.Group with quadtree indexing (pygame install required)
66
+ from fastquadtree.pygame import Group # Mostly drop-in replacement for pygame.sprite.Group with quadtree indexing (pygame install required)
67
67
  ```
@@ -8,7 +8,10 @@ from collections.abc import Sequence
8
8
  from typing import Any, Generic, TypeVar
9
9
 
10
10
  from ._common import (
11
+ FLAG_CORE_CODEC_WINCODE,
12
+ FLAG_MAX_DEPTH_PRESENT,
11
13
  SERIALIZATION_FORMAT_VERSION,
14
+ UNSUPPORTED_BINCODE_MESSAGE,
12
15
  Bounds,
13
16
  QuadTreeDType,
14
17
  SerializationError,
@@ -17,6 +20,7 @@ from ._common import (
17
20
  parse_container,
18
21
  validate_bounds,
19
22
  validate_np_dtype,
23
+ validate_preallocation_limit_bucket,
20
24
  )
21
25
  from ._insert_result import InsertResult
22
26
 
@@ -54,7 +58,13 @@ class _BaseQuadTree(Generic[G], ABC):
54
58
 
55
59
  @classmethod
56
60
  @abstractmethod
57
- def _new_native_from_bytes(cls, data: bytes, dtype: QuadTreeDType) -> Any:
61
+ def _new_native_from_bytes(
62
+ cls,
63
+ data: bytes,
64
+ dtype: QuadTreeDType,
65
+ preallocation_limit_bytes: int | None = None,
66
+ disable_preallocation_limit: bool = False,
67
+ ) -> Any:
58
68
  """Create the native engine instance from serialized bytes."""
59
69
 
60
70
  # ---- Initialization ----
@@ -301,9 +311,9 @@ class _BaseQuadTree(Generic[G], ABC):
301
311
  """
302
312
  core_bytes = self._native.to_bytes()
303
313
 
304
- flags = 0
314
+ flags = FLAG_CORE_CODEC_WINCODE
305
315
  if self._max_depth is not None:
306
- flags |= 1 # max_depth_present
316
+ flags |= FLAG_MAX_DEPTH_PRESENT
307
317
 
308
318
  return build_container(
309
319
  fmt_ver=SERIALIZATION_FORMAT_VERSION,
@@ -319,16 +329,37 @@ class _BaseQuadTree(Generic[G], ABC):
319
329
  )
320
330
 
321
331
  @classmethod
322
- def from_bytes(cls, data: bytes) -> _BaseQuadTree[G]:
332
+ def from_bytes(
333
+ cls,
334
+ data: bytes,
335
+ preallocation_limit_bytes: int | None = None,
336
+ disable_preallocation_limit: bool = False,
337
+ ) -> _BaseQuadTree[G]:
323
338
  """
324
339
  Deserialize a quadtree from bytes.
325
340
 
326
341
  Args:
327
342
  data: Bytes from to_bytes().
343
+ preallocation_limit_bytes: Optional native decode preallocation limit.
344
+ Must be one of the supported bucket values in bytes:
345
+ 1024, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824.
346
+ If omitted, defaults to 67108864 bytes (64 MiB).
347
+ disable_preallocation_limit: Explicitly disable native preallocation
348
+ limits. Use only for trusted data.
328
349
 
329
350
  Returns:
330
351
  A new instance.
352
+
353
+ Raises:
354
+ SerializationError: If the container is malformed, the format version
355
+ is unsupported, or the payload uses legacy bincode encoding.
356
+ ValueError: If the requested preallocation bucket is invalid, or if
357
+ decoding would exceed the configured preallocation limit.
331
358
  """
359
+ validate_preallocation_limit_bucket(
360
+ preallocation_limit_bytes, disable_preallocation_limit
361
+ )
362
+
332
363
  parsed = parse_container(data)
333
364
 
334
365
  fmt_ver = parsed["fmt_ver"]
@@ -337,6 +368,8 @@ class _BaseQuadTree(Generic[G], ABC):
337
368
  f"Unsupported serialization format version {fmt_ver}; "
338
369
  f"this package supports up to {SERIALIZATION_FORMAT_VERSION}"
339
370
  )
371
+ if fmt_ver < 2 or not (parsed["flags"] & FLAG_CORE_CODEC_WINCODE):
372
+ raise SerializationError(UNSUPPORTED_BINCODE_MESSAGE)
340
373
 
341
374
  dtype = parsed["dtype"]
342
375
  core = parsed["core"]
@@ -348,6 +381,8 @@ class _BaseQuadTree(Generic[G], ABC):
348
381
  qt._max_depth = parsed["max_depth"]
349
382
  qt._next_id = parsed["next_id"]
350
383
  qt._count = parsed["count"]
351
- qt._native = cls._new_native_from_bytes(core, dtype)
384
+ qt._native = cls._new_native_from_bytes(
385
+ core, dtype, preallocation_limit_bytes, disable_preallocation_limit
386
+ )
352
387
 
353
388
  return qt
@@ -9,9 +9,12 @@ from collections.abc import Sequence
9
9
  from typing import Any, Generic, TypeVar
10
10
 
11
11
  from ._common import (
12
+ FLAG_CORE_CODEC_WINCODE,
13
+ FLAG_MAX_DEPTH_PRESENT,
12
14
  SECTION_ITEMS,
13
15
  SECTION_OBJECTS,
14
16
  SERIALIZATION_FORMAT_VERSION,
17
+ UNSUPPORTED_BINCODE_MESSAGE,
15
18
  Bounds,
16
19
  Point,
17
20
  QuadTreeDType,
@@ -21,6 +24,7 @@ from ._common import (
21
24
  parse_container,
22
25
  validate_bounds,
23
26
  validate_np_dtype,
27
+ validate_preallocation_limit_bucket,
24
28
  )
25
29
  from ._insert_result import InsertResult
26
30
  from ._item import Item
@@ -210,7 +214,13 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
210
214
 
211
215
  @classmethod
212
216
  @abstractmethod
213
- def _new_native_from_bytes(cls, data: bytes, dtype: QuadTreeDType) -> Any:
217
+ def _new_native_from_bytes(
218
+ cls,
219
+ data: bytes,
220
+ dtype: QuadTreeDType,
221
+ preallocation_limit_bytes: int | None = None,
222
+ disable_preallocation_limit: bool = False,
223
+ ) -> Any:
214
224
  """Create the native engine instance from serialized bytes."""
215
225
 
216
226
  @staticmethod
@@ -704,9 +714,9 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
704
714
  """
705
715
  core_bytes = self._native.to_bytes()
706
716
 
707
- flags = 0
717
+ flags = FLAG_CORE_CODEC_WINCODE
708
718
  if self._max_depth is not None:
709
- flags |= 1 # max_depth_present
719
+ flags |= FLAG_MAX_DEPTH_PRESENT
710
720
 
711
721
  # Always store items (id + geom) safely.
712
722
  items_payload = _encode_items_section(list(self._store.items()))
@@ -731,7 +741,11 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
731
741
 
732
742
  @classmethod
733
743
  def from_bytes(
734
- cls, data: bytes, allow_objects: bool = False
744
+ cls,
745
+ data: bytes,
746
+ allow_objects: bool = False,
747
+ preallocation_limit_bytes: int | None = None,
748
+ disable_preallocation_limit: bool = False,
735
749
  ) -> _BaseQuadTreeObjects[G, ItemType]:
736
750
  """
737
751
  Deserialize a quadtree from bytes.
@@ -740,6 +754,12 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
740
754
  data: Bytes from to_bytes().
741
755
  allow_objects: If True, load pickled Python objects (unsafe).
742
756
  If False (default), object payloads are silently ignored.
757
+ preallocation_limit_bytes: Optional native decode preallocation limit.
758
+ Must be one of the supported bucket values in bytes:
759
+ 1024, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824.
760
+ If omitted, defaults to 67108864 bytes (64 MiB).
761
+ disable_preallocation_limit: Explicitly disable native preallocation
762
+ limits. Use only for trusted data.
743
763
 
744
764
  Returns:
745
765
  A new instance.
@@ -747,7 +767,17 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
747
767
  Note:
748
768
  Object deserialization uses pickle-like semantics. Never load
749
769
  serialized data from untrusted sources with allow_objects=True.
770
+
771
+ Raises:
772
+ SerializationError: If the container is malformed, the format version
773
+ is unsupported, or the payload uses legacy bincode encoding.
774
+ ValueError: If the requested preallocation bucket is invalid, or if
775
+ decoding would exceed the configured preallocation limit.
750
776
  """
777
+ validate_preallocation_limit_bucket(
778
+ preallocation_limit_bytes, disable_preallocation_limit
779
+ )
780
+
751
781
  parsed = parse_container(data)
752
782
 
753
783
  fmt_ver = parsed["fmt_ver"]
@@ -756,6 +786,8 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
756
786
  f"Unsupported serialization format version {fmt_ver}; "
757
787
  f"this package supports up to {SERIALIZATION_FORMAT_VERSION}"
758
788
  )
789
+ if fmt_ver < 2 or not (parsed["flags"] & FLAG_CORE_CODEC_WINCODE):
790
+ raise SerializationError(UNSUPPORTED_BINCODE_MESSAGE)
759
791
 
760
792
  dtype = parsed["dtype"]
761
793
  core = parsed["core"]
@@ -790,7 +822,9 @@ class _BaseQuadTreeObjects(Generic[G, ItemType], ABC):
790
822
  qt._capacity = parsed["capacity"]
791
823
  qt._max_depth = parsed["max_depth"]
792
824
  qt._count = parsed["count"]
793
- qt._native = cls._new_native_from_bytes(core, dtype)
825
+ qt._native = cls._new_native_from_bytes(
826
+ core, dtype, preallocation_limit_bytes, disable_preallocation_limit
827
+ )
794
828
 
795
829
  # Rebuild store from decoded ids/geoms (+ optional objects)
796
830
  store: ObjStore[ItemType] = ObjStore()
@@ -5,13 +5,27 @@ from __future__ import annotations
5
5
  import math
6
6
  from typing import Any, Final, Literal, Union, overload
7
7
 
8
- SERIALIZATION_FORMAT_VERSION: Final[int] = 1
8
+ SERIALIZATION_FORMAT_VERSION: Final[int] = 2
9
9
 
10
10
  # Serialization container constants (shared by Objects and non-Objects trees)
11
11
  SERIALIZATION_MAGIC: Final[bytes] = b"FQT0" # fastquadtree container v0
12
12
  SERIALIZATION_ENDIANNESS: Final[str] = "<" # little-endian
13
+ FLAG_MAX_DEPTH_PRESENT: Final[int] = 1
14
+ FLAG_CORE_CODEC_WINCODE: Final[int] = 1 << 1
15
+ UNSUPPORTED_BINCODE_MESSAGE: Final[str] = (
16
+ "bincode serialization from fastquadtree v2.2 and earlier is no longer supported"
17
+ )
13
18
  SECTION_ITEMS: int = 1 # safe: ids + geometry only
14
19
  SECTION_OBJECTS: int = 2 # unsafe: pickle payload (opt-in)
20
+ NATIVE_PREALLOCATION_LIMIT_BUCKETS: Final[tuple[int, ...]] = (
21
+ 1024,
22
+ 1024 * 1024,
23
+ 4 * 1024 * 1024,
24
+ 16 * 1024 * 1024,
25
+ 64 * 1024 * 1024,
26
+ 256 * 1024 * 1024,
27
+ 1024 * 1024 * 1024,
28
+ )
15
29
 
16
30
  # Type aliases
17
31
  Bounds = tuple[
@@ -132,6 +146,30 @@ def validate_np_dtype(geoms: Any, expected_dtype: QuadTreeDType) -> None:
132
146
  )
133
147
 
134
148
 
149
+ def validate_preallocation_limit_bucket(
150
+ preallocation_limit_bytes: int | None, disable_preallocation_limit: bool
151
+ ) -> None:
152
+ """
153
+ Validate that runtime native decode preallocation limits use a supported bucket.
154
+
155
+ Args:
156
+ preallocation_limit_bytes: Optional requested preallocation limit.
157
+ disable_preallocation_limit: If True, limit validation is skipped.
158
+
159
+ Raises:
160
+ ValueError: If preallocation_limit_bytes is not a supported bucket value.
161
+ """
162
+ if disable_preallocation_limit or preallocation_limit_bytes is None:
163
+ return
164
+
165
+ if preallocation_limit_bytes not in NATIVE_PREALLOCATION_LIMIT_BUCKETS:
166
+ buckets = ", ".join(str(v) for v in NATIVE_PREALLOCATION_LIMIT_BUCKETS)
167
+ raise ValueError(
168
+ "preallocation_limit_bytes must be one of the supported buckets "
169
+ f"(bytes): {buckets}"
170
+ )
171
+
172
+
135
173
  # ---------------------------
136
174
  # Serialization helpers
137
175
  # ---------------------------
@@ -323,7 +361,7 @@ def build_container(
323
361
  )
324
362
 
325
363
  md_bytes = b""
326
- if flags & 1:
364
+ if flags & FLAG_MAX_DEPTH_PRESENT:
327
365
  if max_depth is None:
328
366
  raise SerializationError("max_depth flag set but max_depth is None")
329
367
  if int(max_depth) < 0:
@@ -415,7 +453,7 @@ def parse_container(data: bytes) -> dict[str, Any]:
415
453
  dtype = code_to_dtype(int(dtype_code))
416
454
 
417
455
  max_depth = None
418
- if flags & 1:
456
+ if flags & FLAG_MAX_DEPTH_PRESENT:
419
457
  if len(buf) < off + 4:
420
458
  raise SerializationError("Data too short while reading max_depth")
421
459
  (md,) = struct.unpack_from(f"{SERIALIZATION_ENDIANNESS}i", buf, off)