hashcodecs 0.4.0__tar.gz → 0.5.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 (40) hide show
  1. hashcodecs-0.5.0/BENCHMARK.md +113 -0
  2. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/Cargo.lock +2 -1
  3. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/Cargo.toml +3 -2
  4. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/PKG-INFO +17 -14
  5. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/README.md +15 -12
  6. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/pyproject.toml +1 -1
  7. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/python/hashcodecs/__init__.py +12 -0
  8. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/python/hashcodecs/_hashcodecs.pyi +19 -0
  9. hashcodecs-0.5.0/python/hashcodecs/base64.py +101 -0
  10. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/python/hashcodecs/base64.pyi +15 -0
  11. hashcodecs-0.5.0/src/base64/aarch64.rs +927 -0
  12. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/base64/dispatch.rs +71 -8
  13. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/base64/x86.rs +2 -2
  14. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/base64.rs +166 -5
  15. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/python/base64/encode.rs +44 -40
  16. hashcodecs-0.5.0/src/python/base64.rs +1310 -0
  17. hashcodecs-0.5.0/src/python/buffer.rs +183 -0
  18. hashcodecs-0.5.0/src/python.rs +52 -0
  19. hashcodecs-0.4.0/BENCHMARK.md +0 -71
  20. hashcodecs-0.4.0/python/hashcodecs/base64.py +0 -89
  21. hashcodecs-0.4.0/src/base64/aarch64.rs +0 -292
  22. hashcodecs-0.4.0/src/python/base64.rs +0 -792
  23. hashcodecs-0.4.0/src/python/buffer.rs +0 -113
  24. hashcodecs-0.4.0/src/python.rs +0 -33
  25. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/.gitignore +0 -0
  26. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/LICENSE +0 -0
  27. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/LICENSE-MIT +0 -0
  28. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/benches/base64.rs +0 -0
  29. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/benches/murmur3.rs +0 -0
  30. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/benches/support/mod.rs +0 -0
  31. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/build.rs +0 -0
  32. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/hatch_build.py +0 -0
  33. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/python/hashcodecs/murmur3.py +0 -0
  34. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/python/hashcodecs/py.typed +0 -0
  35. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/base64/x86_avx512.rs +0 -0
  36. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/lib.rs +0 -0
  37. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/murmur3/dispatch.rs +0 -0
  38. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/murmur3/x86.rs +0 -0
  39. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/murmur3.rs +0 -0
  40. {hashcodecs-0.4.0 → hashcodecs-0.5.0}/src/python/murmur3.rs +0 -0
@@ -0,0 +1,113 @@
1
+ # Benchmark Details
2
+
3
+ Environment: Windows 10 x64 and Intel Core Ultra 7 265K.
4
+
5
+ Conditions: clean builds, one pinned logical CPU, single-threaded execution, and 15 Python samples. Higher is better.
6
+
7
+ ## Reusable Python Buffers
8
+
9
+ | Alphabet | Input | Operation | hashcodecs |
10
+ | --- | --- | --- | ---: |
11
+ | Standard | 4 KiB | encode | **15.52 GiB/s** |
12
+ | | 4 KiB | decode | **18.66 GiB/s** |
13
+ | | 1 MiB | encode | **39.91 GiB/s** |
14
+ | | 1 MiB | decode | **29.32 GiB/s** |
15
+ | | 32 MiB | encode | **10.92 GiB/s** |
16
+ | | 32 MiB | decode | **10.40 GiB/s** |
17
+ | URL-safe | 4 KiB | encode | **15.11 GiB/s** |
18
+ | | 4 KiB | decode | **14.43 GiB/s** |
19
+ | | 1 MiB | encode | **39.90 GiB/s** |
20
+ | | 1 MiB | decode | **20.69 GiB/s** |
21
+ | | 32 MiB | encode | **10.89 GiB/s** |
22
+ | | 32 MiB | decode | **10.46 GiB/s** |
23
+
24
+ ## Python Memoryview Inputs
25
+
26
+ Full immutable memoryviews reuse their underlying bytes for inputs of at least 64 KiB.
27
+
28
+ | Input | Operation | Returned `bytes` | Reusable `bytearray` |
29
+ | --- | --- | ---: | ---: |
30
+ | 4 KiB | encode | 8.20 GiB/s | **8.66 GiB/s** |
31
+ | | decode | 9.77 GiB/s | **10.30 GiB/s** |
32
+ | 1 MiB | encode | 3.48 GiB/s | **39.67 GiB/s** |
33
+ | | decode | 4.28 GiB/s | **29.21 GiB/s** |
34
+ | 32 MiB | encode | 2.98 GiB/s | **11.18 GiB/s** |
35
+ | | decode | 3.50 GiB/s | **10.49 GiB/s** |
36
+
37
+ ## Python Base64 Batches
38
+
39
+ Each value is total input throughput; the parenthesized figure is items per second. Higher is better.
40
+
41
+ | Item | Batch | Operation | hashcodecs | hashcodecs loop | pybase64 loop | CPython loop |
42
+ | ---: | ---: | --- | ---: | ---: | ---: | ---: |
43
+ | 16 B | 8 | encode | **0.38 GiB/s (25.36M)** | 0.25 GiB/s (16.81M) | 0.12 GiB/s (8.22M) | 0.19 GiB/s (12.45M) |
44
+ | | | decode | **0.35 GiB/s (23.69M)** | 0.20 GiB/s (13.27M) | 0.08 GiB/s (5.35M) | 0.12 GiB/s (7.95M) |
45
+ | 16 B | 64 | encode | **0.45 GiB/s (30.25M)** | 0.28 GiB/s (18.62M) | 0.14 GiB/s (9.17M) | 0.21 GiB/s (13.78M) |
46
+ | | | decode | **0.47 GiB/s (31.62M)** | 0.23 GiB/s (15.41M) | 0.09 GiB/s (5.96M) | 0.13 GiB/s (8.87M) |
47
+ | 16 B | 1,024 | encode | **0.48 GiB/s (32.40M)** | 0.27 GiB/s (18.38M) | 0.14 GiB/s (9.09M) | 0.20 GiB/s (13.14M) |
48
+ | | | decode | **0.48 GiB/s (32.06M)** | 0.23 GiB/s (15.15M) | 0.08 GiB/s (5.69M) | 0.13 GiB/s (8.39M) |
49
+ | 256 B | 8 | encode | 1.69 GiB/s (7.07M) | 1.42 GiB/s (5.98M) | **1.85 GiB/s (7.76M)** | 0.40 GiB/s (1.68M) |
50
+ | | | decode | **4.98 GiB/s (20.89M)** | 2.91 GiB/s (12.20M) | 1.18 GiB/s (4.93M) | 0.74 GiB/s (3.09M) |
51
+ | 256 B | 64 | encode | 1.84 GiB/s (7.73M) | 1.47 GiB/s (6.17M) | **1.93 GiB/s (8.10M)** | 0.39 GiB/s (1.64M) |
52
+ | | | decode | **6.09 GiB/s (25.52M)** | 3.17 GiB/s (13.31M) | 1.28 GiB/s (5.35M) | 0.78 GiB/s (3.28M) |
53
+ | 256 B | 1,024 | encode | 1.78 GiB/s (7.47M) | 1.50 GiB/s (6.27M) | **1.87 GiB/s (7.83M)** | 0.37 GiB/s (1.55M) |
54
+ | | | decode | **5.75 GiB/s (24.10M)** | 2.99 GiB/s (12.55M) | 1.23 GiB/s (5.17M) | 0.72 GiB/s (3.04M) |
55
+ | 4 KiB | 8 | encode | **14.24 GiB/s (3.73M)** | 12.84 GiB/s (3.37M) | 12.27 GiB/s (3.22M) | 0.46 GiB/s (0.12M) |
56
+ | | | decode | **18.68 GiB/s (4.90M)** | 15.88 GiB/s (4.16M) | 7.86 GiB/s (2.06M) | 1.14 GiB/s (0.30M) |
57
+ | 4 KiB | 64 | encode | **12.37 GiB/s (3.24M)** | 11.32 GiB/s (2.97M) | 9.57 GiB/s (2.51M) | 0.48 GiB/s (0.13M) |
58
+ | | | decode | **19.14 GiB/s (5.02M)** | 16.16 GiB/s (4.24M) | 8.09 GiB/s (2.12M) | 1.13 GiB/s (0.30M) |
59
+ | 4 KiB | 1,024 | encode | 2.03 GiB/s (0.53M) | **2.46 GiB/s (0.65M)** | 2.35 GiB/s (0.62M) | 0.41 GiB/s (0.11M) |
60
+ | | | decode | **13.93 GiB/s (3.65M)** | 12.14 GiB/s (3.18M) | 7.13 GiB/s (1.87M) | 1.11 GiB/s (0.29M) |
61
+
62
+ ## Reusable Python Base64 Batch Buffers
63
+
64
+ Each value is total input throughput for the `*_batch_into` APIs with one reusable `bytearray` per item.
65
+
66
+ | Item | Batch | Encode | Decode |
67
+ | ---: | ---: | ---: | ---: |
68
+ | 16 B | 8 | 0.33 GiB/s | 0.30 GiB/s |
69
+ | | 64 | 0.47 GiB/s | 0.44 GiB/s |
70
+ | | 1,024 | 0.47 GiB/s | 0.45 GiB/s |
71
+ | 256 B | 8 | 1.57 GiB/s | 4.01 GiB/s |
72
+ | | 64 | 1.73 GiB/s | 5.51 GiB/s |
73
+ | | 1,024 | 1.73 GiB/s | 5.29 GiB/s |
74
+ | 4 KiB | 8 | 15.39 GiB/s | 20.29 GiB/s |
75
+ | | 64 | 16.28 GiB/s | 22.12 GiB/s |
76
+ | | 1,024 | 12.95 GiB/s | 16.67 GiB/s |
77
+
78
+ ## Large Python Base64 Batches
79
+
80
+ Each value is total input throughput for 1 MiB items.
81
+
82
+ | Batch | Returned encode | Reusable encode | Returned decode | Reusable decode |
83
+ | ---: | ---: | ---: | ---: | ---: |
84
+ | 1 | 3.52 GiB/s | **39.63 GiB/s** | 3.81 GiB/s | **29.12 GiB/s** |
85
+ | 2 | 3.31 GiB/s | **20.90 GiB/s** | 3.99 GiB/s | **21.50 GiB/s** |
86
+ | 4 | 3.19 GiB/s | **20.15 GiB/s** | 3.91 GiB/s | **21.00 GiB/s** |
87
+ | 8 | 3.17 GiB/s | **19.45 GiB/s** | 3.87 GiB/s | **18.99 GiB/s** |
88
+ | 16 | 2.97 GiB/s | **12.96 GiB/s** | 3.68 GiB/s | **12.18 GiB/s** |
89
+ | 32 | 2.88 GiB/s | **11.09 GiB/s** | 3.29 GiB/s | **10.60 GiB/s** |
90
+
91
+ ## Mutable Python Inputs
92
+
93
+ ### Base64
94
+
95
+ | Input | Operation | Returned `bytes` | Reusable `bytearray` |
96
+ | --- | --- | ---: | ---: |
97
+ | 4 KiB | encode | 13.90 GiB/s | **15.22 GiB/s** |
98
+ | | decode | 16.57 GiB/s | **18.27 GiB/s** |
99
+ | 1 MiB | encode | 3.13 GiB/s | **39.59 GiB/s** |
100
+ | | decode | 3.67 GiB/s | **29.24 GiB/s** |
101
+ | 32 MiB | encode | 2.99 GiB/s | **11.20 GiB/s** |
102
+ | | decode | 3.65 GiB/s | **10.70 GiB/s** |
103
+
104
+ ### MurmurHash3
105
+
106
+ | Variant | API | 4 KiB | 1 MiB | 32 MiB |
107
+ | --- | --- | ---: | ---: | ---: |
108
+ | x86 32-bit | one-shot | **3.79 GiB/s** | **3.98 GiB/s** | **3.97 GiB/s** |
109
+ | | incremental | **3.58 GiB/s** | **3.96 GiB/s** | **3.92 GiB/s** |
110
+ | x86 128-bit | one-shot | **8.09 GiB/s** | **9.22 GiB/s** | **9.12 GiB/s** |
111
+ | | incremental | **7.02 GiB/s** | **9.17 GiB/s** | **9.01 GiB/s** |
112
+ | x64 128-bit | one-shot | **8.68 GiB/s** | **10.10 GiB/s** | **9.54 GiB/s** |
113
+ | | incremental | **7.70 GiB/s** | **10.01 GiB/s** | **9.41 GiB/s** |
@@ -194,12 +194,13 @@ dependencies = [
194
194
 
195
195
  [[package]]
196
196
  name = "hashcodecs"
197
- version = "0.4.0"
197
+ version = "0.5.0"
198
198
  dependencies = [
199
199
  "base64",
200
200
  "base64-turbo",
201
201
  "criterion",
202
202
  "fastmurmur3",
203
+ "memchr",
203
204
  "mimalloc",
204
205
  "mm3h",
205
206
  "murmur3",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "hashcodecs"
3
- version = "0.4.0"
3
+ version = "0.5.0"
4
4
  edition = "2024"
5
5
  rust-version = "1.89"
6
6
  description = "SIMD-accelerated Base64 codecs and fast MurmurHash3 implementations"
@@ -16,10 +16,11 @@ name = "hashcodecs"
16
16
  crate-type = ["rlib", "cdylib"]
17
17
 
18
18
  [features]
19
- python = ["dep:pyo3"]
19
+ python = ["dep:memchr", "dep:pyo3"]
20
20
  extension-module = ["python", "pyo3/extension-module"]
21
21
 
22
22
  [dependencies]
23
+ memchr = { version = "2.8.0", optional = true }
23
24
  mimalloc = "0.1.52"
24
25
  pyo3 = { version = "0.29.2", features = ["abi3-py310"], optional = true }
25
26
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: hashcodecs
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: SIMD-accelerated Base64 and MurmurHash3 codecs
5
5
  License-Expression: MIT OR Apache-2.0
6
6
  License-File: LICENSE
@@ -21,6 +21,7 @@ Description-Content-Type: text/markdown
21
21
  # hashcodecs
22
22
 
23
23
  [![CI](https://img.shields.io/github/actions/workflow/status/kozistr/hashcodecs-rs/ci.yml?branch=main&style=for-the-badge&logo=github)](https://github.com/kozistr/hashcodecs-rs/actions/workflows/ci.yml)
24
+ [![Codecov](https://codecov.io/gh/kozistr/hashcodecs-rs/graph/badge.svg)](https://app.codecov.io/gh/kozistr/hashcodecs-rs)
24
25
  [![PyPI](https://img.shields.io/pypi/v/hashcodecs?style=for-the-badge&logo=pypi)](https://pypi.org/project/hashcodecs/)
25
26
  [![Python](https://img.shields.io/pypi/pyversions/hashcodecs?style=for-the-badge&logo=python)](https://pypi.org/project/hashcodecs/)
26
27
  [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-brightgreen?style=for-the-badge)](https://github.com/kozistr/hashcodecs-rs#license)
@@ -105,7 +106,9 @@ uv sync --group benchmark --no-install-project
105
106
  uv run --no-project --with . python benchmarks/python_base64.py
106
107
  uv run --no-project --with . python benchmarks/python_base64.py --into
107
108
  uv run --no-project --with . python benchmarks/python_base64.py --bytearray-input
109
+ uv run --no-project --with . python benchmarks/python_base64.py --memoryview-input
108
110
  uv run --no-project --with . python benchmarks/python_base64_batch.py
111
+ uv run --no-project --with . python benchmarks/python_base64_batch.py --large
109
112
  uv run --no-project --with . python benchmarks/python_murmur3.py
110
113
  uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
111
114
  ```
@@ -147,18 +150,18 @@ Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly i
147
150
 
148
151
  | Alphabet | Input | Operation | hashcodecs | CPython `base64` | `pybase64` |
149
152
  | --- | --- | --- | ---: | ---: | ---: |
150
- | Standard | 4 KiB | encode | 13.57 GiB/s | 0.48 GiB/s | **14.06 GiB/s** |
151
- | | 4 KiB | decode | **16.70 GiB/s** | 1.13 GiB/s | 8.47 GiB/s |
152
- | | 1 MiB | encode | **3.28 GiB/s** | 0.44 GiB/s | 3.02 GiB/s |
153
- | | 1 MiB | decode | **4.02 GiB/s** | 0.95 GiB/s | 3.68 GiB/s |
154
- | | 32 MiB | encode | **2.92 GiB/s** | 0.43 GiB/s | 2.84 GiB/s |
155
- | | 32 MiB | decode | 3.40 GiB/s | 0.94 GiB/s | **3.69 GiB/s** |
156
- | URL-safe | 4 KiB | encode | **12.63 GiB/s** | 0.41 GiB/s | 1.19 GiB/s |
157
- | | 4 KiB | decode | **11.34 GiB/s** | 0.76 GiB/s | 1.56 GiB/s |
158
- | | 1 MiB | encode | **3.24 GiB/s** | 0.36 GiB/s | 0.91 GiB/s |
159
- | | 1 MiB | decode | **4.15 GiB/s** | 0.63 GiB/s | 1.45 GiB/s |
160
- | | 32 MiB | encode | **3.03 GiB/s** | 0.36 GiB/s | 0.90 GiB/s |
161
- | | 32 MiB | decode | **3.40 GiB/s** | 0.61 GiB/s | 1.48 GiB/s |
153
+ | Standard | 4 KiB | encode | **14.42 GiB/s** | 0.49 GiB/s | 14.36 GiB/s |
154
+ | | 4 KiB | decode | **16.72 GiB/s** | 1.12 GiB/s | 8.35 GiB/s |
155
+ | | 1 MiB | encode | **3.69 GiB/s** | 0.43 GiB/s | 3.51 GiB/s |
156
+ | | 1 MiB | decode | **4.90 GiB/s** | 0.97 GiB/s | 4.60 GiB/s |
157
+ | | 32 MiB | encode | **2.81 GiB/s** | 0.44 GiB/s | 2.60 GiB/s |
158
+ | | 32 MiB | decode | 3.15 GiB/s | 0.93 GiB/s | **3.49 GiB/s** |
159
+ | URL-safe | 4 KiB | encode | **14.48 GiB/s** | 0.40 GiB/s | 1.19 GiB/s |
160
+ | | 4 KiB | decode | **13.45 GiB/s** | 0.75 GiB/s | 1.56 GiB/s |
161
+ | | 1 MiB | encode | **3.96 GiB/s** | 0.36 GiB/s | 0.92 GiB/s |
162
+ | | 1 MiB | decode | **4.53 GiB/s** | 0.61 GiB/s | 1.58 GiB/s |
163
+ | | 32 MiB | encode | **2.64 GiB/s** | 0.34 GiB/s | 0.83 GiB/s |
164
+ | | 32 MiB | decode | **3.15 GiB/s** | 0.60 GiB/s | 1.49 GiB/s |
162
165
 
163
166
  ## MurmurHash3: Python
164
167
 
@@ -1,6 +1,7 @@
1
1
  # hashcodecs
2
2
 
3
3
  [![CI](https://img.shields.io/github/actions/workflow/status/kozistr/hashcodecs-rs/ci.yml?branch=main&style=for-the-badge&logo=github)](https://github.com/kozistr/hashcodecs-rs/actions/workflows/ci.yml)
4
+ [![Codecov](https://codecov.io/gh/kozistr/hashcodecs-rs/graph/badge.svg)](https://app.codecov.io/gh/kozistr/hashcodecs-rs)
4
5
  [![PyPI](https://img.shields.io/pypi/v/hashcodecs?style=for-the-badge&logo=pypi)](https://pypi.org/project/hashcodecs/)
5
6
  [![Python](https://img.shields.io/pypi/pyversions/hashcodecs?style=for-the-badge&logo=python)](https://pypi.org/project/hashcodecs/)
6
7
  [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-brightgreen?style=for-the-badge)](https://github.com/kozistr/hashcodecs-rs#license)
@@ -85,7 +86,9 @@ uv sync --group benchmark --no-install-project
85
86
  uv run --no-project --with . python benchmarks/python_base64.py
86
87
  uv run --no-project --with . python benchmarks/python_base64.py --into
87
88
  uv run --no-project --with . python benchmarks/python_base64.py --bytearray-input
89
+ uv run --no-project --with . python benchmarks/python_base64.py --memoryview-input
88
90
  uv run --no-project --with . python benchmarks/python_base64_batch.py
91
+ uv run --no-project --with . python benchmarks/python_base64_batch.py --large
89
92
  uv run --no-project --with . python benchmarks/python_murmur3.py
90
93
  uv run --no-project --with . python benchmarks/python_murmur3.py --incremental
91
94
  ```
@@ -127,18 +130,18 @@ Python decoding uses `validate=True`, and `hashcodecs` passes `bytes` directly i
127
130
 
128
131
  | Alphabet | Input | Operation | hashcodecs | CPython `base64` | `pybase64` |
129
132
  | --- | --- | --- | ---: | ---: | ---: |
130
- | Standard | 4 KiB | encode | 13.57 GiB/s | 0.48 GiB/s | **14.06 GiB/s** |
131
- | | 4 KiB | decode | **16.70 GiB/s** | 1.13 GiB/s | 8.47 GiB/s |
132
- | | 1 MiB | encode | **3.28 GiB/s** | 0.44 GiB/s | 3.02 GiB/s |
133
- | | 1 MiB | decode | **4.02 GiB/s** | 0.95 GiB/s | 3.68 GiB/s |
134
- | | 32 MiB | encode | **2.92 GiB/s** | 0.43 GiB/s | 2.84 GiB/s |
135
- | | 32 MiB | decode | 3.40 GiB/s | 0.94 GiB/s | **3.69 GiB/s** |
136
- | URL-safe | 4 KiB | encode | **12.63 GiB/s** | 0.41 GiB/s | 1.19 GiB/s |
137
- | | 4 KiB | decode | **11.34 GiB/s** | 0.76 GiB/s | 1.56 GiB/s |
138
- | | 1 MiB | encode | **3.24 GiB/s** | 0.36 GiB/s | 0.91 GiB/s |
139
- | | 1 MiB | decode | **4.15 GiB/s** | 0.63 GiB/s | 1.45 GiB/s |
140
- | | 32 MiB | encode | **3.03 GiB/s** | 0.36 GiB/s | 0.90 GiB/s |
141
- | | 32 MiB | decode | **3.40 GiB/s** | 0.61 GiB/s | 1.48 GiB/s |
133
+ | Standard | 4 KiB | encode | **14.42 GiB/s** | 0.49 GiB/s | 14.36 GiB/s |
134
+ | | 4 KiB | decode | **16.72 GiB/s** | 1.12 GiB/s | 8.35 GiB/s |
135
+ | | 1 MiB | encode | **3.69 GiB/s** | 0.43 GiB/s | 3.51 GiB/s |
136
+ | | 1 MiB | decode | **4.90 GiB/s** | 0.97 GiB/s | 4.60 GiB/s |
137
+ | | 32 MiB | encode | **2.81 GiB/s** | 0.44 GiB/s | 2.60 GiB/s |
138
+ | | 32 MiB | decode | 3.15 GiB/s | 0.93 GiB/s | **3.49 GiB/s** |
139
+ | URL-safe | 4 KiB | encode | **14.48 GiB/s** | 0.40 GiB/s | 1.19 GiB/s |
140
+ | | 4 KiB | decode | **13.45 GiB/s** | 0.75 GiB/s | 1.56 GiB/s |
141
+ | | 1 MiB | encode | **3.96 GiB/s** | 0.36 GiB/s | 0.92 GiB/s |
142
+ | | 1 MiB | decode | **4.53 GiB/s** | 0.61 GiB/s | 1.58 GiB/s |
143
+ | | 32 MiB | encode | **2.64 GiB/s** | 0.34 GiB/s | 0.83 GiB/s |
144
+ | | 32 MiB | decode | **3.15 GiB/s** | 0.60 GiB/s | 1.49 GiB/s |
142
145
 
143
146
  ## MurmurHash3: Python
144
147
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hashcodecs"
7
- version = "0.4.0"
7
+ version = "0.5.0"
8
8
  description = "SIMD-accelerated Base64 and MurmurHash3 codecs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -3,21 +3,27 @@
3
3
  from .base64 import (
4
4
  b64decode,
5
5
  b64decode_batch,
6
+ b64decode_batch_into,
6
7
  b64decode_into,
7
8
  b64encode,
8
9
  b64encode_batch,
10
+ b64encode_batch_into,
9
11
  b64encode_into,
10
12
  standard_b64decode,
11
13
  standard_b64decode_batch,
14
+ standard_b64decode_batch_into,
12
15
  standard_b64decode_into,
13
16
  standard_b64encode,
14
17
  standard_b64encode_batch,
18
+ standard_b64encode_batch_into,
15
19
  standard_b64encode_into,
16
20
  urlsafe_b64decode,
17
21
  urlsafe_b64decode_batch,
22
+ urlsafe_b64decode_batch_into,
18
23
  urlsafe_b64decode_into,
19
24
  urlsafe_b64encode,
20
25
  urlsafe_b64encode_batch,
26
+ urlsafe_b64encode_batch_into,
21
27
  urlsafe_b64encode_into,
22
28
  )
23
29
  from .murmur3 import (
@@ -32,9 +38,11 @@ from .murmur3 import (
32
38
  __all__ = [
33
39
  'b64decode',
34
40
  'b64decode_batch',
41
+ 'b64decode_batch_into',
35
42
  'b64decode_into',
36
43
  'b64encode',
37
44
  'b64encode_batch',
45
+ 'b64encode_batch_into',
38
46
  'b64encode_into',
39
47
  'murmur3_32',
40
48
  'murmur3_x64_128',
@@ -44,14 +52,18 @@ __all__ = [
44
52
  'murmur3_x86_128_digest',
45
53
  'standard_b64decode',
46
54
  'standard_b64decode_batch',
55
+ 'standard_b64decode_batch_into',
47
56
  'standard_b64decode_into',
48
57
  'standard_b64encode',
49
58
  'standard_b64encode_batch',
59
+ 'standard_b64encode_batch_into',
50
60
  'standard_b64encode_into',
51
61
  'urlsafe_b64decode',
52
62
  'urlsafe_b64decode_batch',
63
+ 'urlsafe_b64decode_batch_into',
53
64
  'urlsafe_b64decode_into',
54
65
  'urlsafe_b64encode',
55
66
  'urlsafe_b64encode_batch',
67
+ 'urlsafe_b64encode_batch_into',
56
68
  'urlsafe_b64encode_into',
57
69
  ]
@@ -8,6 +8,11 @@ def b64encode(
8
8
  wrapcol: int = 0,
9
9
  ) -> bytes: ...
10
10
  def b64encode_batch(items: list[ReadableBuffer], altchars: ReadableBuffer | None = None) -> list[bytes]: ...
11
+ def b64encode_batch_into(
12
+ items: list[ReadableBuffer],
13
+ outputs: list[bytearray],
14
+ altchars: ReadableBuffer | None = None,
15
+ ) -> list[int]: ...
11
16
  def b64encode_into(
12
17
  s: ReadableBuffer,
13
18
  output: bytearray,
@@ -30,6 +35,12 @@ def b64decode_batch(
30
35
  altchars: str | ReadableBuffer | None = None,
31
36
  validate: bool = False,
32
37
  ) -> list[bytes]: ...
38
+ def b64decode_batch_into(
39
+ items: list[str | ReadableBuffer],
40
+ outputs: list[bytearray],
41
+ altchars: str | ReadableBuffer | None = None,
42
+ validate: bool = False,
43
+ ) -> list[int]: ...
33
44
  def b64decode_into(
34
45
  s: str | ReadableBuffer,
35
46
  output: bytearray,
@@ -40,6 +51,14 @@ def b64decode_into(
40
51
  ignorechars: ReadableBuffer = ...,
41
52
  canonical: bool = False,
42
53
  ) -> int: ...
54
+ def standard_b64encode(s: ReadableBuffer) -> bytes: ...
55
+ def standard_b64encode_into(s: ReadableBuffer, output: bytearray) -> int: ...
56
+ def standard_b64decode(s: str | ReadableBuffer) -> bytes: ...
57
+ def standard_b64decode_into(s: str | ReadableBuffer, output: bytearray) -> int: ...
58
+ def urlsafe_b64encode(s: ReadableBuffer, *, padded: bool = True) -> bytes: ...
59
+ def urlsafe_b64encode_into(s: ReadableBuffer, output: bytearray, *, padded: bool = True) -> int: ...
60
+ def urlsafe_b64decode(s: str | ReadableBuffer, *, padded: bool = ...) -> bytes: ...
61
+ def urlsafe_b64decode_into(s: str | ReadableBuffer, output: bytearray, *, padded: bool = ...) -> int: ...
43
62
  def murmur3_32(s: ReadableBuffer, seed: int = 0) -> int: ...
44
63
  def murmur3_x86_128_digest(s: ReadableBuffer, seed: int = 0) -> bytes: ...
45
64
  def murmur3_x64_128_digest(s: ReadableBuffer, seed: int = 0) -> bytes: ...
@@ -0,0 +1,101 @@
1
+ """A fast, API-compatible subset of Python's :mod:`base64` module."""
2
+
3
+ from ._hashcodecs import (
4
+ b64decode,
5
+ b64decode_batch,
6
+ b64decode_batch_into,
7
+ b64decode_into,
8
+ b64encode,
9
+ b64encode_batch,
10
+ b64encode_batch_into,
11
+ b64encode_into,
12
+ standard_b64decode,
13
+ standard_b64decode_into,
14
+ standard_b64encode,
15
+ standard_b64encode_into,
16
+ urlsafe_b64decode,
17
+ urlsafe_b64decode_into,
18
+ urlsafe_b64encode,
19
+ urlsafe_b64encode_into,
20
+ )
21
+
22
+ for _function in (
23
+ standard_b64decode,
24
+ standard_b64decode_into,
25
+ standard_b64encode,
26
+ standard_b64encode_into,
27
+ urlsafe_b64decode,
28
+ urlsafe_b64decode_into,
29
+ urlsafe_b64encode,
30
+ urlsafe_b64encode_into,
31
+ ):
32
+ _function.__module__ = __name__
33
+ del _function
34
+
35
+
36
+ def standard_b64encode_batch(items) -> list[bytes]:
37
+ """Encode a list of inputs with the standard Base64 alphabet."""
38
+ return b64encode_batch(items)
39
+
40
+
41
+ def standard_b64encode_batch_into(items, outputs: list[bytearray]) -> list[int]:
42
+ """Encode a list of inputs with the standard alphabet into reusable outputs."""
43
+ return b64encode_batch_into(items, outputs)
44
+
45
+
46
+ def standard_b64decode_batch(items) -> list[bytes]:
47
+ """Decode a list of inputs with the standard Base64 alphabet."""
48
+ return b64decode_batch(items)
49
+
50
+
51
+ def standard_b64decode_batch_into(items, outputs: list[bytearray]) -> list[int]:
52
+ """Decode a list of standard Base64 inputs into reusable outputs."""
53
+ return b64decode_batch_into(items, outputs)
54
+
55
+
56
+ def urlsafe_b64encode_batch(items) -> list[bytes]:
57
+ """Encode a list of inputs with the URL-safe Base64 alphabet."""
58
+ return b64encode_batch(items, b'-_')
59
+
60
+
61
+ def urlsafe_b64encode_batch_into(items, outputs: list[bytearray]) -> list[int]:
62
+ """Encode a list of inputs with the URL-safe alphabet into reusable outputs."""
63
+ return b64encode_batch_into(items, outputs, b'-_')
64
+
65
+
66
+ def urlsafe_b64decode_batch(items) -> list[bytes]:
67
+ """Decode a list of inputs with the URL-safe Base64 alphabet."""
68
+ return b64decode_batch(items, b'-_')
69
+
70
+
71
+ def urlsafe_b64decode_batch_into(items, outputs: list[bytearray]) -> list[int]:
72
+ """Decode a list of URL-safe Base64 inputs into reusable outputs."""
73
+ return b64decode_batch_into(items, outputs, b'-_')
74
+
75
+
76
+ __all__ = [
77
+ 'b64decode',
78
+ 'b64decode_batch',
79
+ 'b64decode_batch_into',
80
+ 'b64decode_into',
81
+ 'b64encode',
82
+ 'b64encode_batch',
83
+ 'b64encode_batch_into',
84
+ 'b64encode_into',
85
+ 'standard_b64decode',
86
+ 'standard_b64decode_batch',
87
+ 'standard_b64decode_batch_into',
88
+ 'standard_b64decode_into',
89
+ 'standard_b64encode',
90
+ 'standard_b64encode_batch',
91
+ 'standard_b64encode_batch_into',
92
+ 'standard_b64encode_into',
93
+ 'urlsafe_b64decode',
94
+ 'urlsafe_b64decode_batch',
95
+ 'urlsafe_b64decode_batch_into',
96
+ 'urlsafe_b64decode_into',
97
+ 'urlsafe_b64encode',
98
+ 'urlsafe_b64encode_batch',
99
+ 'urlsafe_b64encode_batch_into',
100
+ 'urlsafe_b64encode_into',
101
+ ]
@@ -8,6 +8,11 @@ def b64encode(
8
8
  wrapcol: int = 0,
9
9
  ) -> bytes: ...
10
10
  def b64encode_batch(items: list[ReadableBuffer], altchars: ReadableBuffer | None = None) -> list[bytes]: ...
11
+ def b64encode_batch_into(
12
+ items: list[ReadableBuffer],
13
+ outputs: list[bytearray],
14
+ altchars: ReadableBuffer | None = None,
15
+ ) -> list[int]: ...
11
16
  def b64encode_into(
12
17
  s: ReadableBuffer,
13
18
  output: bytearray,
@@ -30,6 +35,12 @@ def b64decode_batch(
30
35
  altchars: str | ReadableBuffer | None = None,
31
36
  validate: bool = False,
32
37
  ) -> list[bytes]: ...
38
+ def b64decode_batch_into(
39
+ items: list[str | ReadableBuffer],
40
+ outputs: list[bytearray],
41
+ altchars: str | ReadableBuffer | None = None,
42
+ validate: bool = False,
43
+ ) -> list[int]: ...
33
44
  def b64decode_into(
34
45
  s: str | ReadableBuffer,
35
46
  output: bytearray,
@@ -42,13 +53,17 @@ def b64decode_into(
42
53
  ) -> int: ...
43
54
  def standard_b64encode(s: ReadableBuffer) -> bytes: ...
44
55
  def standard_b64encode_batch(items: list[ReadableBuffer]) -> list[bytes]: ...
56
+ def standard_b64encode_batch_into(items: list[ReadableBuffer], outputs: list[bytearray]) -> list[int]: ...
45
57
  def standard_b64encode_into(s: ReadableBuffer, output: bytearray) -> int: ...
46
58
  def standard_b64decode(s: str | ReadableBuffer) -> bytes: ...
47
59
  def standard_b64decode_batch(items: list[str | ReadableBuffer]) -> list[bytes]: ...
60
+ def standard_b64decode_batch_into(items: list[str | ReadableBuffer], outputs: list[bytearray]) -> list[int]: ...
48
61
  def standard_b64decode_into(s: str | ReadableBuffer, output: bytearray) -> int: ...
49
62
  def urlsafe_b64encode(s: ReadableBuffer, *, padded: bool = True) -> bytes: ...
50
63
  def urlsafe_b64encode_batch(items: list[ReadableBuffer]) -> list[bytes]: ...
64
+ def urlsafe_b64encode_batch_into(items: list[ReadableBuffer], outputs: list[bytearray]) -> list[int]: ...
51
65
  def urlsafe_b64encode_into(s: ReadableBuffer, output: bytearray, *, padded: bool = True) -> int: ...
52
66
  def urlsafe_b64decode(s: str | ReadableBuffer, *, padded: bool = ...) -> bytes: ...
53
67
  def urlsafe_b64decode_batch(items: list[str | ReadableBuffer]) -> list[bytes]: ...
68
+ def urlsafe_b64decode_batch_into(items: list[str | ReadableBuffer], outputs: list[bytearray]) -> list[int]: ...
54
69
  def urlsafe_b64decode_into(s: str | ReadableBuffer, output: bytearray, *, padded: bool = ...) -> int: ...